Skip to content

Instantly share code, notes, and snippets.

@PsychoH13
Created April 6, 2010 21:15
Show Gist options
  • Save PsychoH13/358133 to your computer and use it in GitHub Desktop.
Save PsychoH13/358133 to your computer and use it in GitHub Desktop.
/*
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
/*
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