// // HOMUtilities.m // HigherOrderMessaging // // Created by Ofri Wolfus on 23/12/05. // Copyright 2005 Ofri Wolfus. All rights reserved. // #import "HOMUtilities.h" #include //Renames originalSelector instance method of inClass to newSelector. BOOL hom_renameInstnaceMethod(Class inClass, SEL originalSelector, SEL newSelector) { Method method = NULL; //Look for the method method = class_getInstanceMethod(inClass, originalSelector); if(method != NULL) { //Rename the method method->method_name = newSelector; return YES; } else return NO; } //Renames originalSelector class method of inClass to newSelector. BOOL hom_renameClassMethod(Class inClass, SEL originalSelector, SEL newSelector) { Method method = NULL; //Look for the method method = class_getClassMethod(inClass, originalSelector); if(method != NULL) { //Rename the method method->method_name = newSelector; return YES; } else return NO; } //Rplaces the IMP of originalSelector instance method of classOne with the imp of newSelector of classTwo. //Returns the original IMP of originalSelector. IMP hom_replaceInstanceIMP(Class classOne, SEL originalSelector, Class classTwo, SEL newSelector) { Method originalMethod = NULL; Method newMethod = NULL; IMP originalIMP = NULL; //Find the original method originalMethod = class_getInstanceMethod(classOne, originalSelector); //Find the new method newMethod = class_getInstanceMethod(classTwo, newSelector); if(originalMethod != NULL && newMethod != NULL) { //Save the original IMP originalIMP = originalMethod->method_imp; //Replace the IMPs originalMethod->method_imp = newMethod->method_imp; } return originalIMP; } //Rplaces the IMP of originalSelector class method of classOne with the imp of newSelector of classTwo. //Returns the original IMP of originalSelector. IMP hom_replaceClassIMP(Class classOne, SEL originalSelector, Class classTwo, SEL newSelector) { Method originalMethod = NULL; Method newMethod = NULL; IMP originalIMP = NULL; //Find the original method originalMethod = class_getClassMethod(classOne, originalSelector); //Find the new method newMethod = class_getClassMethod(classTwo, newSelector); if(originalMethod != NULL && newMethod != NULL) { //Save the original IMP originalIMP = originalMethod->method_imp; //Replace the IMPs originalMethod->method_imp = newMethod->method_imp; } return originalIMP; } /*********************************************************************** * HOMSubtypeUntil. * * Delegation. * Code taken from Apple's Objective-C runtime, released under ASPL. **********************************************************************/ static int HOMSubtypeUntil (const char * type, char end) { int level = 0; const char * head = type; // while (*type) { if (!*type || (!level && (*type == end))) return (int)(type - head); switch (*type) { case ']': case '}': case ')': level--; break; case '[': case '{': case '(': level += 1; break; } type += 1; } //_objc_fatal ("Object: SubtypeUntil: end of type encountered prematurely\n"); return 0; } /*********************************************************************** * HOMSkipFirstType. * Code taken from Apple's Objective-C runtime, released under ASPL. **********************************************************************/ static const char * HOMSkipFirstType (const char * type) { while (1) { switch (*type++) { case 'O': /* bycopy */ case 'n': /* in */ case 'o': /* out */ case 'N': /* inout */ case 'r': /* const */ case 'V': /* oneway */ case '^': /* pointers */ break; /* arrays */ case '[': while ((*type >= '0') && (*type <= '9')) type += 1; return type + HOMSubtypeUntil (type, ']') + 1; /* structures */ case '{': return type + HOMSubtypeUntil (type, '}') + 1; /* unions */ case '(': return type + HOMSubtypeUntil (type, ')') + 1; /* basic types */ default: return type; } } } const char * hom_getArgumentFromTypes(const char *types, unsigned index) { unsigned i = 0; // First, skip the return type types = HOMSkipFirstType(types); // Next, skip stack size while ((*types >= '0') && (*types <= '9')) types += 1; for (i = 0; i < index; i++) { // Traverse argument type types = HOMSkipFirstType (types); // Skip GNU runtime's register parameter hint if (*types == '+') types++; // Traverse (possibly negative) argument offset if (*types == '-') types += 1; while ((*types >= '0') && (*types <= '9')) types += 1; } return types; } /* * Gets the type of an argument at a given index. * Modified from method_getNumberOfArguments() in Apple's Objective-C runtime. * Apple's runtime is released under the ASPL v2.0. */ /*const char * hom_getArgumentTypeAtIndex(Method m, unsigned index) { const char *typedesc = m->method_types; unsigned i = 0; // First, skip the return type typedesc = HOMSkipFirstType(typedesc); // Next, skip stack size while ((*typedesc >= '0') && (*typedesc <= '9')) typedesc += 1; for (i = 0; i < index; i++) { // Traverse argument type typedesc = HOMSkipFirstType (typedesc); // Skip GNU runtime's register parameter hint if (*typedesc == '+') typedesc++; // Traverse (possibly negative) argument offset if (*typedesc == '-') typedesc += 1; while ((*typedesc >= '0') && (*typedesc <= '9')) typedesc += 1; } return typedesc; }*/ const char * hom_getArgumentTypeAtIndex(Method m, unsigned index) { return hom_getArgumentFromTypes(m->method_types, index); } char * hom_copyArgumentTypeAtIndex(Method m, unsigned index) { const char *typedesc = hom_getArgumentTypeAtIndex(m, index); char *type; const char *end; end = HOMSkipFirstType (typedesc); type = malloc(end - typedesc + sizeof(char)); strncpy(type, typedesc, sizeof(char) * (end - typedesc)); return type; } int hom_getArgumentOffsetAtIndex(Method m, unsigned index) { return atoi(HOMSkipFirstType(hom_getArgumentTypeAtIndex(m, index))); } int hom_getArgumentOffsetFromTypes(const char *types, unsigned index) { return atoi(HOMSkipFirstType(hom_getArgumentFromTypes(types, index))); }