Created
April 6, 2010 21:15
-
-
Save PsychoH13/358133 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (c) 2008, Remy Demarest | |
All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
* Neither the name of the Remy Demarest nor the | |
names of its contributors may be used to endorse or promote products | |
derived from this software without specific prior written permission. | |
THIS SOFTWARE IS PROVIDED BY Remy Demarest ''AS IS'' AND ANY | |
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
DISCLAIMED. IN NO EVENT SHALL Remy Demarest BE LIABLE FOR ANY | |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
#import <Cocoa/Cocoa.h> | |
#import <objc/runtime.h> | |
#import <objc/message.h> | |
EXTERN_C_BEGIN | |
typedef int (*CompFunc)(const void *, const void *); | |
extern const Class kPSYSuperClass; | |
void PSYMethodListForSuperClassesOfClass(Class aClass); | |
void PSYMethodListForClass(Class aClass); | |
void PSYSort(void *array, size_t elementSize, size_t count, CompFunc compare, BOOL asc); | |
int PSYCompareClassSizes(const void *ptr1, const void *ptr2); | |
int PSYCompareClassNames(const void *ptr1, const void *ptr2); | |
int PSYCompareClasses(const void *ptr1, const void *ptr2); | |
int PSYNumberOfSuperClasses(Class cls); | |
Class PSYGetSuperClassAtLevel(Class cls, int lvl); | |
void PSYGetClassesUnderCommonSuper(Class *cls1, Class *cls2); | |
void PSYShowAllClasses(void); | |
void PSYPrintClassDescription(Class cls); | |
void PSYPrintClassDescriptionWithout(Class cls, Class avoid); | |
unsigned PSYPrintAllClassMethodsWithout(Class cls, Class avoid); | |
void PSYPrintSuperClassesOfClass(Class aClass); | |
void PSYPrintProtocolsOfClass(Class aClass); | |
int PSYCompareIvars(const void *ptr1, const void *ptr2); | |
int PSYCompareMethods(const void *ptr1, const void *ptr2); | |
int PSYCompareProperties(const void *ptr1, const void *ptr2); | |
unsigned PSYPrintAllClassIvars(Class cls); | |
unsigned PSYPrintAllClassMethods(Class cls); | |
unsigned PSYPrintAllProperties(Class cls); | |
void PSYPrintProtocolDescription(Protocol *p); | |
EXTERN_C_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (c) 2008, Remy Demarest | |
All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
* Neither the name of the Remy Demarest nor the | |
names of its contributors may be used to endorse or promote products | |
derived from this software without specific prior written permission. | |
THIS SOFTWARE IS PROVIDED BY Remy Demarest ''AS IS'' AND ANY | |
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
DISCLAIMED. IN NO EVENT SHALL Remy Demarest BE LIABLE FOR ANY | |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
#import "ClassCompare.h" | |
#include <stdio.h> | |
#include <string.h> | |
extern void PSYSort(void *array, size_t elementSize, size_t count, CompFunc compare, BOOL asc); | |
#define SWAP(type, obj1, obj2) do { \ | |
type temp = obj1; \ | |
obj1 = obj2; \ | |
obj2 = temp; \ | |
} while(0) | |
int PSYNumberOfSuperClasses(Class cls) { | |
if(cls == Nil) return -1; | |
Class super = class_getSuperclass(cls); | |
if(super == Nil) return 0; | |
return PSYNumberOfSuperClasses(super) + 1; | |
} | |
int PSYCompareClassSizes(const void *ptr1, const void *ptr2) | |
{ | |
Class cls1 = *(Class *)ptr1, cls2 = *(Class *)ptr2; | |
return class_getInstanceSize(cls1) - class_getInstanceSize(cls2); | |
} | |
int PSYCompareClassNames(const void *ptr1, const void *ptr2) | |
{ | |
Class cls1 = *(Class *)ptr1, cls2 = *(Class *)ptr2; | |
return strcmp(class_getName(cls1), class_getName(cls2)); | |
} | |
Class PSYGetSuperClassAtLevel(Class cls, int lvl) { | |
if(lvl <= 0) return cls; | |
Class temp = class_getSuperclass(cls); | |
if(temp == Nil) return cls; | |
return PSYGetSuperClassAtLevel(temp, lvl-1); | |
} | |
void PSYGetClassesUnderCommonSuper(Class *cls1, Class *cls2) { | |
Class temp1 = class_getSuperclass(*cls1), | |
temp2 = class_getSuperclass(*cls2); | |
if(temp1 == temp2) return; | |
*cls1 = temp1; | |
*cls2 = temp2; | |
PSYGetClassesUnderCommonSuper(cls1, cls2); | |
} | |
int PSYCompareClasses(const void *ptr1, const void *ptr2) { | |
Class cls1 = *(Class *)ptr1, cls2 = *(Class *)ptr2; | |
if(cls1 == cls2) return 0; | |
BOOL cls1IsUp = YES; | |
int upSprCnt = PSYNumberOfSuperClasses(cls1); | |
int downSprCnt = PSYNumberOfSuperClasses(cls2); | |
cls1IsUp = (upSprCnt < downSprCnt); | |
if(!cls1IsUp) SWAP(int, upSprCnt, downSprCnt); | |
Class temp = PSYGetSuperClassAtLevel((cls1IsUp ? cls2 : cls1), | |
downSprCnt - upSprCnt); | |
if(temp == (cls1IsUp ? cls1 : cls2)) return (cls1IsUp ? -1 : 1); | |
if(cls1IsUp) cls2 = temp; | |
else cls1 = temp; | |
Class temp1 = cls1, temp2 = cls2; | |
PSYGetClassesUnderCommonSuper(&temp1, &temp2); | |
if(temp1 != Nil && temp2 != Nil) | |
cls1 = temp1, cls2 = temp2; | |
/*int cmp = compareClassSizes(cls1, cls2); | |
if(cmp != 0) return cmp;*/ | |
return PSYCompareClassNames(cls1, cls2); | |
} | |
void PSYPrintSuperClassesOfClass(Class aClass) { | |
Class super = class_getSuperclass(aClass); | |
if(super != nil) PSYPrintSuperClassesOfClass(super); | |
printf("%s%s", (super ? " : " : ""), class_getName(aClass)); | |
PSYPrintProtocolsOfClass(aClass); | |
} | |
void PSYPrintProtocolsOfClass(Class aClass) | |
{ | |
Protocol **protocols = class_copyProtocolList(aClass, NULL); | |
if(protocols != NULL) | |
{ | |
Protocol **pro = protocols; | |
printf(" <"); | |
while(*pro != NULL) | |
{ | |
printf("%s", protocol_getName(*pro)); | |
pro++; | |
if(*pro != NULL) printf(", "); | |
} | |
printf(">"); | |
free(protocols); | |
} | |
} | |
void PSYShowAllClasses(void) | |
{ | |
int numClasses; | |
Class * classes = NULL; | |
classes = NULL; | |
numClasses = objc_getClassList(NULL, 0); | |
int nbClass[10] = {0}; | |
if (numClasses > 0 ) | |
{ | |
classes = malloc(sizeof(Class) * numClasses); | |
numClasses = objc_getClassList(classes, numClasses); | |
PSYSort(classes, sizeof(Class), numClasses, PSYCompareClasses, YES); | |
for(int i = 0; i < numClasses; i++) | |
{ | |
Class temp = classes[i]; | |
int nbSuperClass = PSYNumberOfSuperClasses(temp); | |
nbClass[nbSuperClass]++; | |
printf("- % 5d : (% 5zi)[%d] ", i, | |
class_getInstanceSize(temp), | |
nbSuperClass); | |
PSYPrintSuperClassesOfClass(temp); | |
printf("\n"); | |
} | |
NSLog(@"Classe racines : %d", nbClass[0]); | |
for(int i = 1; i < 10 && nbClass[i] != 0; i++) | |
NSLog(@"Classe niv[%d] : %d", i, nbClass[i]); | |
free(classes); | |
} | |
NSLog(@"registered = %d", numClasses); | |
} | |
int PSYCompareIvars(const void *ptr1, const void *ptr2) { | |
Ivar iv1 = *(Ivar *)ptr1, iv2 = *(Ivar *)ptr2; | |
return ivar_getOffset(iv1) - ivar_getOffset(iv2); | |
} | |
int PSYCompareMethods(const void *ptr1, const void *ptr2) { | |
Method m1 = *(Method *)ptr1, m2 = *(Method *)ptr2; | |
return strcmp(sel_getName(method_getName(m1)), sel_getName(method_getName(m2))); | |
} | |
int PSYCompareProperties(const void *ptr1, const void *ptr2) { | |
objc_property_t p1 = *(objc_property_t *)ptr1, p2 = *(objc_property_t *)ptr2; | |
return strcmp(property_getName(p1), property_getName(p2)); | |
} | |
void printMethodList(Method *mList, unsigned cnt, char type) { | |
printf("\t\t%s methods : %d\n", (type == '+' ? "Class" : "Instance"), cnt); | |
for(unsigned i = 0; i < cnt; i++) | |
{ | |
Method temp = mList[i]; | |
char *t = method_copyReturnType(temp); | |
printf("\t\t%c (%s)", type, t); | |
free(t); | |
printf("%s\t", sel_getName(method_getName(temp))); | |
unsigned count = method_getNumberOfArguments(temp); | |
for(unsigned j = 2; j < count; j++) | |
{ | |
t = method_copyArgumentType(temp, j); | |
printf("'%s' ", t); | |
free(t); | |
} | |
printf("\n"); | |
} | |
} | |
unsigned PSYPrintAllClassMethods(Class cls) { | |
unsigned methodCount = 0; | |
Class super = class_getSuperclass(cls); | |
if(super != Nil) methodCount = PSYPrintAllClassMethods(super); | |
printf("\tClass : %s\n", class_getName(cls)); | |
unsigned cnt; | |
// Class methods : | |
Method *mList = class_copyMethodList(object_getClass(cls), &cnt); | |
methodCount += cnt; | |
PSYSort(mList, sizeof(Method), cnt, PSYCompareMethods, YES); | |
printMethodList(mList, cnt, '+'); | |
free(mList); | |
// Instance methods : | |
mList = class_copyMethodList(cls, &cnt); | |
methodCount += cnt; | |
PSYSort(mList, sizeof(Method), cnt, PSYCompareMethods, YES); | |
printMethodList(mList, cnt, '-'); | |
free(mList); | |
printf("\n"); | |
return methodCount; | |
} | |
unsigned PSYPrintAllClassIvars(Class cls) { | |
unsigned ivarCount = 0; | |
Class super = class_getSuperclass(cls); | |
if(super != Nil) ivarCount = PSYPrintAllClassIvars(super); | |
unsigned cnt = 0; | |
Ivar *list = class_copyIvarList(cls, &cnt); | |
ivarCount += cnt; | |
PSYSort(list, sizeof(Ivar), cnt, PSYCompareIvars, YES); | |
printf("\tClass : %s (%d)\n", class_getName(cls), cnt); | |
for(unsigned i = 0; i < cnt; i++) | |
{ | |
Ivar temp = list[i]; | |
printf("\t\t%s\t\t %s\n", ivar_getTypeEncoding(temp), ivar_getName(temp)); | |
} | |
free(list); | |
return ivarCount; | |
} | |
unsigned PSYPrintAllProperties(Class cls) { | |
unsigned propCount = 0; | |
Class super = class_getSuperclass(cls); | |
if(super != Nil) propCount = PSYPrintAllProperties(super); | |
unsigned cnt = 0; | |
objc_property_t *list = class_copyPropertyList(cls, &cnt); | |
propCount += cnt; | |
PSYSort(list, sizeof(objc_property_t), cnt, PSYCompareIvars, YES); | |
printf("\tClass : %s\n", class_getName(cls)); | |
printf("\t\tProperties : %d\n\t\tName, Attributes\n", cnt); | |
for(unsigned i = 0; i < cnt; i++) | |
{ | |
objc_property_t temp = list[i]; | |
printf("\t\t%s,\t\t %s\n", property_getName(temp), property_getAttributes(temp)); | |
} | |
free(list); | |
return propCount; | |
} | |
const Class kPSYSuperClass = (Class)@"kSuperClass"; | |
unsigned PSYPrintAllClassMethodsWithout(Class cls, Class avoid) { | |
if(cls == avoid) return 0; | |
unsigned methodCount = 0; | |
if(avoid != kPSYSuperClass) | |
{ | |
Class super = class_getSuperclass(cls); | |
if(super != Nil) methodCount = PSYPrintAllClassMethodsWithout(super, avoid); | |
} | |
printf("\tClass : %s\n", class_getName(cls)); | |
unsigned cnt; | |
// Class methods : | |
Method *mList = class_copyMethodList(object_getClass(cls), &cnt); | |
methodCount += cnt; | |
PSYSort(mList, sizeof(Method), cnt, PSYCompareMethods, YES); | |
printMethodList(mList, cnt, '+'); | |
free(mList); | |
// Instance methods : | |
mList = class_copyMethodList(cls, &cnt); | |
methodCount += cnt; | |
PSYSort(mList, sizeof(Method), cnt, PSYCompareMethods, YES); | |
printMethodList(mList, cnt, '-'); | |
free(mList); | |
printf("\n"); | |
return methodCount; | |
} | |
void PSYPrintClassDescriptionWithout(Class cls, Class avoid) { | |
printf("Start ----------------------------\n"); | |
printf("Class : %s\n", class_getName(cls)); | |
PSYPrintSuperClassesOfClass(cls); | |
printf("\n"); | |
printf("Ivars : {\n"); | |
unsigned ivarCount = PSYPrintAllClassIvars(cls); | |
printf("}\n"); | |
printf("Methods :\n"); | |
unsigned methodCount = PSYPrintAllClassMethodsWithout(cls, avoid); | |
printf("Properties :\n"); | |
unsigned propCount = PSYPrintAllProperties(cls); | |
printf("Total Ivars = %d\nTotal Methods = %d\nTotal Properties = %d", ivarCount, methodCount, propCount); | |
printf("\nEnd ------------------------------\n"); | |
} | |
void PSYPrintClassDescription(Class cls) { | |
printf("Start ----------------------------\n"); | |
printf("Class : %s\n", class_getName(cls)); | |
PSYPrintSuperClassesOfClass(cls); | |
printf("\n"); | |
printf("Ivars : {\n"); | |
unsigned ivarCount = PSYPrintAllClassIvars(cls); | |
printf("}\n"); | |
printf("Methods :\n"); | |
unsigned methodCount = PSYPrintAllClassMethods(cls); | |
printf("Properties :\n"); | |
unsigned propCount = PSYPrintAllProperties(cls); | |
printf("Total Ivars = %d\nTotal Methods = %d\nTotal Properties = %d", ivarCount, methodCount, propCount); | |
printf("\nEnd ------------------------------\n"); | |
} | |
int compareMethodDescriptions(const void *ptr1, const void *ptr2) { | |
struct objc_method_description m1 = *(struct objc_method_description *)ptr1, m2 = *(struct objc_method_description *)ptr2; | |
return strcmp(sel_getName(m1.name), sel_getName(m2.name)); | |
} | |
void printMethodDescriptionList(struct objc_method_description *mList, unsigned cnt, char type) | |
{ | |
for(unsigned i = 0; i < cnt; i++) | |
{ | |
struct objc_method_description temp = mList[i]; | |
printf("\t%c %s %s\n", type, sel_getName(temp.name), temp.types); | |
} | |
} | |
void PSYPrintProtocolDescription(Protocol *p) | |
{ | |
if(p == NULL) return; | |
printf("Start ----------------------------\n"); | |
printf("@protocol %s", protocol_getName(p)); | |
Protocol **conf = protocol_copyProtocolList(p, NULL); | |
if(conf != NULL) | |
{ | |
Protocol **current = conf; | |
printf(" <"); | |
while(*current != NULL) | |
{ | |
printf("%s", protocol_getName(*current)); | |
current++; | |
if(*current != NULL) printf(", "); | |
} | |
printf(">\n"); | |
free(conf); | |
} | |
printf("\n@required\n"); | |
unsigned cnt; | |
// Class methods : | |
struct objc_method_description *mList = protocol_copyMethodDescriptionList(p, YES, NO, &cnt); | |
PSYSort(mList, sizeof(struct objc_method_description), cnt, compareMethodDescriptions, YES); | |
printMethodDescriptionList(mList, cnt, '+'); | |
free(mList); | |
mList = protocol_copyMethodDescriptionList(p, YES, YES, &cnt); | |
PSYSort(mList, sizeof(struct objc_method_description), cnt, compareMethodDescriptions, YES); | |
printMethodDescriptionList(mList, cnt, '-'); | |
free(mList); | |
printf("@optional\n"); | |
mList = protocol_copyMethodDescriptionList(p, NO, NO, &cnt); | |
PSYSort(mList, sizeof(struct objc_method_description), cnt, compareMethodDescriptions, YES); | |
printMethodDescriptionList(mList, cnt, '+'); | |
free(mList); | |
mList = protocol_copyMethodDescriptionList(p, NO, YES, &cnt); | |
PSYSort(mList, sizeof(struct objc_method_description), cnt, compareMethodDescriptions, YES); | |
printMethodDescriptionList(mList, cnt, '-'); | |
free(mList); | |
printf("\nEnd ------------------------------\n"); | |
} | |
BOOL shouldReverse(int comp, BOOL asc) | |
{ | |
if(asc) return comp < 0; | |
else return comp > 0; | |
} | |
void PSYSort(void *array, size_t elementSize, size_t count, CompFunc compare, BOOL asc) | |
{ | |
void *temp, *eli, *elj; | |
temp = malloc(elementSize); | |
for(size_t i = 0; i < count; i++) | |
{ | |
for(size_t j = 0; j < count; j++) | |
{ | |
if(i == j) continue; | |
eli = array + i * elementSize; | |
elj = array + j * elementSize; | |
if(shouldReverse(compare(eli, elj), asc)) | |
{ | |
memcpy(temp, eli, elementSize); | |
memcpy(eli, elj, elementSize); | |
memcpy(elj, temp, elementSize); | |
} | |
} | |
} | |
free(temp); | |
} | |
void PSYMethodListForSuperClassesOfClass(Class aClass) | |
{ | |
if(aClass == Nil) return; | |
Class super = class_getSuperclass(aClass); | |
PSYMethodListForSuperClassesOfClass(super); | |
PSYMethodListForClass(aClass); | |
} | |
void PSYMethodListForClass(Class aClass) | |
{ | |
printf("\tClass = %s", class_getName(aClass)); | |
unsigned count = 0; | |
Method *methodList = class_copyMethodList(aClass, &count); | |
printf("\t*** Method count: %u ***\n", count); | |
for(unsigned i = 0; i < count; i++) | |
{ | |
Method m = methodList[i]; | |
unsigned argCount = method_getNumberOfArguments(m); | |
printf("\t- Method description for method[%u]: %s\n", i, | |
sel_getName(method_getName(m))); | |
printf("\t\t*** Argument count: %u ***\n", argCount); | |
char *type = method_copyReturnType(m); | |
printf("\t\t- return type = %s\n", type); | |
free(type); | |
for(unsigned j = 0; j < argCount; j++) | |
{ | |
type = method_copyArgumentType(m, j); | |
printf("\t\t- type for argument[%u] = %s\n", j, type); | |
free(type); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment