28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
|
static void
register_selectors(struct objc_abi_category *cat)
{
for (struct objc_abi_method_list *ml = cat->instance_methods;
ml != NULL; ml = ml->next)
for (unsigned int i = 0; i < ml->count; i++)
objc_register_selector(
(struct objc_abi_selector*)&ml->methods[i]);
(struct objc_abi_selector *)&ml->methods[i]);
for (struct objc_abi_method_list *ml = cat->class_methods;
ml != NULL; ml = ml->next)
for (unsigned int i = 0; i < ml->count; i++)
objc_register_selector(
(struct objc_abi_selector*)&ml->methods[i]);
(struct objc_abi_selector *)&ml->methods[i]);
}
static void
register_category(struct objc_abi_category *cat)
{
struct objc_abi_category **cats;
Class cls = objc_classname_to_class(cat->class_name, false);
if (categories == NULL)
categories = objc_hashtable_new(
objc_hash_string, objc_equal_string, 2);
cats = (struct objc_abi_category**)objc_hashtable_get(categories,
cats = (struct objc_abi_category **)objc_hashtable_get(categories,
cat->class_name);
if (cats != NULL) {
struct objc_abi_category **ncats;
size_t i;
for (i = 0; cats[i] != NULL; i++);
if ((ncats = realloc(cats,
(i + 2) * sizeof(struct objc_abi_category*))) == NULL)
(i + 2) * sizeof(struct objc_abi_category *))) == NULL)
OBJC_ERROR("Not enough memory for category %s of "
"class %s!", cat->category_name, cat->class_name);
ncats[i] = cat;
ncats[i + 1] = NULL;
objc_hashtable_set(categories, cat->class_name, ncats);
if (cls != Nil && cls->info & OBJC_CLASS_INFO_SETUP) {
objc_update_dtable(cls);
objc_update_dtable(cls->isa);
}
return;
}
if ((cats = malloc(2 * sizeof(struct objc_abi_category*))) == NULL)
if ((cats = malloc(2 * sizeof(struct objc_abi_category *))) == NULL)
OBJC_ERROR("Not enough memory for category %s of class %s!\n",
cat->category_name, cat->class_name);
cats[0] = cat;
cats[1] = NULL;
objc_hashtable_set(categories, cat->class_name, cats);
if (cls != Nil && cls->info & OBJC_CLASS_INFO_SETUP) {
objc_update_dtable(cls);
objc_update_dtable(cls->isa);
}
}
void
objc_register_all_categories(struct objc_abi_symtab *symtab)
{
struct objc_abi_category **cats =
(struct objc_abi_category**)symtab->defs + symtab->cls_def_cnt;
(struct objc_abi_category **)symtab->defs + symtab->cls_def_cnt;
for (size_t i = 0; i < symtab->cat_def_cnt; i++) {
register_selectors(cats[i]);
register_category(cats[i]);
}
}
struct objc_category**
struct objc_category **
objc_categories_for_class(Class cls)
{
if (categories == NULL)
return NULL;
return (struct objc_category**)objc_hashtable_get(categories,
return (struct objc_category **)objc_hashtable_get(categories,
cls->name);
}
void
objc_unregister_all_categories(void)
{
if (categories == NULL)
return;
for (uint32_t i = 0; i < categories->size; i++)
if (categories->data[i] != NULL)
free((void*)categories->data[i]->obj);
free((void *)categories->data[i]->obj);
objc_hashtable_free(categories);
categories = NULL;
}
|