| /* the following macros will create a mechanism to box common cocoa structures so can be easily added to NSArrays etc | |
| * | |
| * The macros can take multiple arguments allowing you to pass in an existing struct, or the components of the struct | |
| * | |
| * for example: | |
| * NSValue * pointValue1 = @point(3,5); // pass in the two values that make up the point | |
| * | |
| * NSPoint * myPoint = NSMakePoint(3,5); | |
| * NSValue * pointValue2 = @point(myPoint); // pass in a existing point. | |
| * | |
| * NSArray * frames = @[@rect([self frame]),@rect(10,10,50,50)]; | |
| * | |
| * How this works... | |
| * | |
| * point(...) is a macro that that takes a variable number of arguments (but really should be 1 or 2 args for points) | |
| * and will expand to one of two function calls depending on the number of arguments to the macro. | |
| * valueFromPoint1_(NSPoint p) or | |
| * valueFromPoint2_(CGFloat x, CGFloat y) | |
| * these functions do the actual boxing (making an NSValue) | |
| */ | |
| #import <Foundation/Foundation.h> | |
| // macros to deal with variable number of arguments to the boxing macros | |
| #define PP_ARG_N( \ | |
| _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ | |
| _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ | |
| _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ | |
| _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ | |
| _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ | |
| _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ | |
| _61, _62, _63, N, ...) N | |
| #define PP_RSEQ_N() \ | |
| 62, 61, 60, \ | |
| 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ | |
| 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ | |
| 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ | |
| 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ | |
| 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ | |
| 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 | |
| #define PP_NARG_(...) PP_ARG_N(__VA_ARGS__) | |
| #define PP_NARG(...) PP_NARG_(_, ##__VA_ARGS__, PP_RSEQ_N()) | |
| // macros to expand the base function name to append the number of args in the macro. | |
| #define BOX_(a,b,...) a ## b ## _(__VA_ARGS__) // have to add an extra _ | |
| #define BOX(a,b,...) BOX_(a,b,__VA_ARGS__) | |
| // the specific macros -- calling the BOX macro with the baseFunctionName, the number of args, and the arg list | |
| // | |
| // Not that it uses the YES?Macro:0 format to enable the @ prefix eg @point(1,2) | |
| // the YES eats the @ -- the @YES will alway evaluate true so the first option is used. -- the second is not used ; | |
| // techically format is not needed and you could get rid of the YES? ... :0 parts of the macro | |
| // but then it would look like point(1,2) -- which doesn't look much like a box expression :) | |
| // | |
| #define point(...) YES?BOX(valueFromPoint, PP_NARG(__VA_ARGS__),__VA_ARGS__):0 | |
| #define rect(...) YES?BOX(valueFromRect, PP_NARG(__VA_ARGS__),__VA_ARGS__):0 | |
| #define size(...) YES?BOX(valueFromSize, PP_NARG(__VA_ARGS__),__VA_ARGS__):0 | |
| #define range(...) YES?BOX(valueFromRange, PP_NARG(__VA_ARGS__),__VA_ARGS__):0 | |
| // the actual boxing functions. Note that the name of the function is critical | |
| // being the baseName (eg valueFromPoint) + number of arguments + _ the underscore is needed for the BOX_ macro to expand. | |
| NSValue * valueFromPoint1_(NSPoint arg1){ | |
| return [NSValue valueWithPoint:arg1]; | |
| } | |
| NSValue * valueFromPoint2_(double x, double y){ | |
| return [NSValue valueWithPoint:NSMakePoint(x, y)]; | |
| } | |
| NSValue * valueFromSize1_(NSSize arg1){ | |
| return [NSValue valueWithSize:arg1]; | |
| } | |
| NSValue * valueFromSize2_(double w, double h){ | |
| return [NSValue valueWithSize:NSMakeSize(w,h)]; | |
| } | |
| NSValue * valueFromRange1_(NSRange arg1){ | |
| return [NSValue valueWithRange:arg1]; | |
| } | |
| NSValue * valueFromRange2_(NSUInteger loc, NSUInteger len){ | |
| return [NSValue valueWithRange:NSMakeRange(loc,len)]; | |
| } | |
| NSValue * valueFromRect1_(NSRect r){ | |
| return [NSValue valueWithRect:r]; | |
| } | |
| NSValue * valueFromRect4_(double x, double y,double w, double h){ | |
| return [NSValue valueWithRect:NSMakeRect(x, y, w, h)]; | |
| } | |
| // Example code | |
| NSPoint pointFunc(){ | |
| return NSMakePoint(3,4); | |
| } | |
| int main(int argc, char *argv[]) { | |
| @autoreleasepool { | |
| NSArray * a = @[@point(1,2), | |
| @point(2,3), | |
| @point(pointFunc()), | |
| @rect(10,10,50,50), | |
| @range(10,30), | |
| @size(5,7)]; | |
| NSLog (@"a: %@ ",a); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment