diff --git a/class.h b/class.h index 8526c84d..44bea6d2 100644 --- a/class.h +++ b/class.h @@ -444,6 +444,23 @@ void freeMethodLists(Class aClass); void objc_load_class(struct objc_class *cls); +/** + * Enumerator for a class table. Must have the same layout as the internal + * version. + */ +struct class_table_enumerator +{ + void *table; + unsigned int seen; + unsigned int index; +}; + +/** + * Iterate over the class table returning the next class and then NULL after + * all classes have been enumerated. + */ +PRIVATE Class class_table_next(struct class_table_enumerator *e); + #ifdef __cplusplus } // extern "C" #endif diff --git a/class_table.c b/class_table.c index 55057edb..3e87e7a3 100644 --- a/class_table.c +++ b/class_table.c @@ -133,12 +133,6 @@ PRIVATE Class class_table_get_safe(const char *class_name) return class_table_internal_table_get(class_table, class_name); } -PRIVATE Class class_table_next(void **e) -{ - return class_table_internal_next(class_table, - (struct class_table_internal_table_enumerator**)e); -} - PRIVATE BOOL objc_resolve_class(Class cls); PRIVATE void init_class_tables(void) { @@ -500,6 +494,11 @@ PRIVATE void class_table_remove(Class cls) class_table_internal_remove(class_table, (void*)cls->name); } +PRIVATE Class class_table_next(struct class_table_enumerator *e) +{ + return class_table_internal_next(class_table, (struct class_table_internal_table_enumerator*)e); +} + //////////////////////////////////////////////////////////////////////////////// // Public API @@ -512,14 +511,13 @@ int objc_getClassList(Class *buffer, int bufferLen) return class_table->table_used; } int count = 0; - struct class_table_internal_table_enumerator *e = NULL; + struct class_table_internal_table_enumerator e = MAP_TABLE_ENUMERATOR_INITIALISER; Class next; while (count < bufferLen && (next = class_table_internal_next(class_table, &e))) { buffer[count++] = next; } - free(e); return count; } Class *objc_copyClassList(unsigned int *outCount) @@ -595,7 +593,18 @@ id objc_get_meta_class(const char *name) Class objc_next_class(void **enum_state) { - return class_table_next ( enum_state); + if (*enum_state == NULL) + { + *enum_state = calloc(1, sizeof(struct class_table_internal_table_enumerator)); + } + Class next = class_table_internal_next(class_table, + *(struct class_table_internal_table_enumerator**)enum_state); + if (next == NULL) + { + free(*enum_state); + *enum_state = NULL; + } + return next; } Class class_pose_as(Class impostor, Class super_class) diff --git a/dtable.c b/dtable.c index e10e7272..b1adf7cc 100644 --- a/dtable.c +++ b/dtable.c @@ -608,8 +608,6 @@ PRIVATE dtable_t create_dtable_for_class(Class class, dtable_t root_dtable) } -Class class_table_next(void **e); - PRIVATE void objc_resize_dtables(uint32_t newSize) { // If dtables already have enough space to store all registered selectors, do nothing @@ -636,7 +634,7 @@ PRIVATE void objc_resize_dtables(uint32_t newSize) } } // Resize all existing dtables - void *e = NULL; + struct class_table_enumerator e = {NULL, 0, 0}; struct objc_class *next; while ((next = class_table_next(&e))) { diff --git a/hash_table.h b/hash_table.h index 10c4a2bd..5f474cd1 100644 --- a/hash_table.h +++ b/hash_table.h @@ -212,6 +212,12 @@ struct PREFIX(_table_enumerator) unsigned int index; }; +/** + * Initialisation value for a new map enumerator. + */ +#define MAP_TABLE_ENUMERATOR_INITIALISER {NULL, 0, 0} + + static inline PREFIX(_table_cell) PREFIX(_table_lookup)(PREFIX(_table) *table, uint32_t hash) { @@ -465,26 +471,25 @@ static MAP_TABLE_VALUE_TYPE* static MAP_TABLE_VALUE_TYPE #endif PREFIX(_next)(PREFIX(_table) *table, - struct PREFIX(_table_enumerator) **state) + struct PREFIX(_table_enumerator) *state) { - if (NULL == *state) + if (NULL == state->table) { - *state = CALLOC(1, sizeof(struct PREFIX(_table_enumerator))); // Make sure that we are not reallocating the table when we start // enumerating MAP_LOCK(); - (*state)->table = table; - (*state)->index = -1; + state->table = table; + state->index = -1; IF_NO_GC(__sync_fetch_and_add(&table->enumerator_count, 1);) MAP_UNLOCK(); } - if ((*state)->seen >= (*state)->table->table_used) + if (state->seen >= state->table->table_used) { #ifndef ENABLE_GC MAP_LOCK(); __sync_fetch_and_sub(&table->enumerator_count, 1); MAP_UNLOCK(); - free(*state); + state->table = NULL; #endif #ifdef MAP_TABLE_ACCESS_BY_REFERENCE return NULL; @@ -492,15 +497,15 @@ PREFIX(_next)(PREFIX(_table) *table, return MAP_TABLE_VALUE_PLACEHOLDER; #endif } - while ((++((*state)->index)) < TABLE_SIZE((*state)->table)) + while ((++(state->index)) < TABLE_SIZE(state->table)) { - if (!MAP_TABLE_VALUE_NULL((*state)->table->table[(*state)->index].value)) + if (!MAP_TABLE_VALUE_NULL(state->table->table[state->index].value)) { - (*state)->seen++; + state->seen++; #ifdef MAP_TABLE_ACCESS_BY_REFERENCE - return &(*state)->table->table[(*state)->index].value; + return &state->table->table[state->index].value; #else - return (*state)->table->table[(*state)->index].value; + return state->table->table[state->index].value; #endif } } @@ -509,7 +514,7 @@ PREFIX(_next)(PREFIX(_table) *table, MAP_LOCK(); table->enumerator_count--; MAP_UNLOCK(); - free(*state); + state->table = NULL; #endif #ifdef MAP_TABLE_ACCESS_BY_REFERENCE return NULL; @@ -529,12 +534,12 @@ static MAP_TABLE_VALUE_TYPE* static MAP_TABLE_VALUE_TYPE #endif PREFIX(_current)(PREFIX(_table) *table, - struct PREFIX(_table_enumerator) **state) + struct PREFIX(_table_enumerator) *state) { #ifdef MAP_TABLE_ACCESS_BY_REFERENCE - return &(*state)->table->table[(*state)->index].value; + return &state->table->table[state->index].value; #else - return (*state)->table->table[(*state)->index].value; + return state->table->table[state->index].value; #endif } diff --git a/protocol.c b/protocol.c index 3028ea27..9eb7e429 100644 --- a/protocol.c +++ b/protocol.c @@ -508,7 +508,7 @@ Protocol*__unsafe_unretained* objc_copyProtocolList(unsigned int *outCount) unsigned int total = known_protocol_table->table_used; Protocol **p = calloc(known_protocol_table->table_used, sizeof(Protocol*)); - struct protocol_table_enumerator *e = NULL; + struct protocol_table_enumerator e = MAP_TABLE_ENUMERATOR_INITIALISER; Protocol *next; unsigned int count = 0; @@ -516,10 +516,6 @@ Protocol*__unsafe_unretained* objc_copyProtocolList(unsigned int *outCount) { p[count++] = next; } - if (NULL != e) - { - free(e); - } if (NULL != outCount) { *outCount = total;