#import "Command.h" #import "OFString+Cube.h" #include <cube.h> static OFArray<OFString *> * padArguments(OFArray<OFString *> *arguments, size_t count) { OFMutableArray<OFString *> *copy; if (arguments.count >= count) return arguments; copy = [arguments mutableCopy]; while (copy.count < count) [copy addObject: @""]; [copy makeImmutable]; return copy; } @implementation Command { id _block; } + (instancetype)commandWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block { return [[self alloc] initWithName: name argumentsTypes: argumentsTypes block: block]; } - (instancetype)initWithName: (OFString *)name argumentsTypes: (int)argumentsTypes block: (id)block { self = [super initWithName: name]; _argumentsTypes = argumentsTypes; _block = block; return self; } - (int)callWithArguments: (OFArray<OFString *> *)arguments isDown: (bool)isDown { switch (_argumentsTypes) { case ARG_1INT: if (isDown) { arguments = padArguments(arguments, 2); ((void (^)(int))_block)( [arguments[1] cube_intValueWithBase: 0]); } break; case ARG_2INT: if (isDown) { arguments = padArguments(arguments, 3); ((void (^)(int, int))_block)( [arguments[1] cube_intValueWithBase: 0], [arguments[2] cube_intValueWithBase: 0]); } break; case ARG_3INT: if (isDown) { arguments = padArguments(arguments, 4); ((void (^)(int, int, int))_block)( [arguments[1] cube_intValueWithBase: 0], [arguments[2] cube_intValueWithBase: 0], [arguments[3] cube_intValueWithBase: 0]); } break; case ARG_4INT: if (isDown) { arguments = padArguments(arguments, 5); ((void (^)(int, int, int, int))_block)( [arguments[1] cube_intValueWithBase: 0], [arguments[2] cube_intValueWithBase: 0], [arguments[3] cube_intValueWithBase: 0], [arguments[4] cube_intValueWithBase: 0]); } break; case ARG_NONE: if (isDown) ((void (^)())_block)(); break; case ARG_1STR: if (isDown) { arguments = padArguments(arguments, 2); ((void (^)(OFString *))_block)(arguments[1]); } break; case ARG_2STR: if (isDown) { arguments = padArguments(arguments, 3); ((void (^)(OFString *, OFString *))_block)( arguments[1], arguments[2]); } break; case ARG_3STR: if (isDown) { arguments = padArguments(arguments, 4); ((void (^)(OFString *, OFString *, OFString *))_block)( arguments[1], arguments[2], arguments[3]); } break; case ARG_5STR: if (isDown) { arguments = padArguments(arguments, 6); ((void (^)(OFString *, OFString *, OFString *, OFString *, OFString *))_block)(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); } break; case ARG_DOWN: ((void (^)(bool))_block)(isDown); break; case ARG_DWN1: arguments = padArguments(arguments, 2); ((void (^)(bool, OFString *))_block)(isDown, arguments[1]); break; case ARG_1EXP: if (isDown) { arguments = padArguments(arguments, 2); return ((int (^)(int))_block)( execute(arguments[1], isDown)); } break; case ARG_2EXP: if (isDown) { arguments = padArguments(arguments, 3); return ((int (^)(int, int))_block)( execute(arguments[1], isDown), execute(arguments[2], isDown)); } break; case ARG_1EST: if (isDown) { arguments = padArguments(arguments, 2); return ((int (^)(OFString *))_block)(arguments[1]); } break; case ARG_2EST: if (isDown) { arguments = padArguments(arguments, 3); return ((int (^)(OFString *, OFString *))_block)( arguments[1], arguments[2]); } break; case ARG_VARI: if (isDown) // limit, remove ((void (^)(OFString *))_block)([[arguments objectsInRange: OFMakeRange(1, arguments.count - 1)] componentsJoinedByString: @" "]); break; } return 0; } @end