ObjFW  Check-in [285e1138bc]

Overview
Comment:Implement basic forwarding.

No need to implement it for the Apple runtime, as the Apple runtime
already tries to call these methods.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 285e1138bc21d86089d8c92a12f9c0b2992f0289d06fe2a82fffc9dd95391f93
User & Date: js on 2012-08-03 22:37:50
Other Links: manifest | tags
Context
2012-08-04
00:00
Add forwarding tests. check-in: 4bcfe4d4bc user: js tags: trunk
2012-08-03
22:37
Implement basic forwarding. check-in: 285e1138bc user: js tags: trunk
20:49
Add class_isMetaClass(). check-in: c50d4f7837 user: js tags: trunk
Changes

Modified src/OFObject.h from [263d460557] to [0b56356200].

475
476
477
478
479
480
481




















482
483
484
485
486
487
488
 * The methods which will be added from the specified class are not allowed to
 * use super or access instance variables, instead they have to use accessors.
 *
 * \param class The class from which the instance methods should be inherited
 */
+ (void)inheritMethodsFromClass: (Class)class_;





















/**
 * \brief Initializes an already allocated object.
 *
 * Derived classes may override this, but need to do self = [super init] before
 * they do any initialization themselves. init may never return nil, instead
 * an exception (for example OFInitializationFailed) should be thrown.
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
 * The methods which will be added from the specified class are not allowed to
 * use super or access instance variables, instead they have to use accessors.
 *
 * \param class The class from which the instance methods should be inherited
 */
+ (void)inheritMethodsFromClass: (Class)class_;

/**
 * \brief Try to resolve the specified class method.
 *
 * This method is called if a class method was not found, so that an
 * implementation can be provided at runtime.
 *
 * \return Whether the method has been added to the class
 */
+ (BOOL)resolveClassMethod: (SEL)selector;

/**
 * \brief Try to resolve the specified instance method.
 *
 * This method is called if an instance method was not found, so that an
 * implementation can be provided at runtime.
 *
 * \return Whether the method has been added to the class
 */
+ (BOOL)resolveInstanceMethod: (SEL)selector;

/**
 * \brief Initializes an already allocated object.
 *
 * Derived classes may override this, but need to do self = [super init] before
 * they do any initialization themselves. init may never return nil, instead
 * an exception (for example OFInitializationFailed) should be thrown.
 *

Modified src/OFObject.m from [8f2badf8fb] to [6f60ff9dfc].

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
extern BOOL objc_properties_init();
#endif

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaught_exception_handler(id exception)
{
	fprintf(stderr, "\nUnhandled exception:\n%s\n",
	    [[exception description] UTF8String]);
}
#endif

static void
enumeration_mutation_handler(id object)
{
	@throw [OFEnumerationMutationException
	    exceptionWithClass: [object class]
			object: object];
}



















































#ifndef HAVE_OBJC_ENUMERATIONMUTATION
void
objc_enumerationMutation(id object)
{
	enumeration_mutation_handler(object);
}







|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
extern BOOL objc_properties_init();
#endif

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaught_exception_handler(id exception)
{
	fprintf(stderr, "\nRuntime error: Unhandled exception:\n%s\n",
	    [[exception description] UTF8String]);
}
#endif

static void
enumeration_mutation_handler(id object)
{
	@throw [OFEnumerationMutationException
	    exceptionWithClass: [object class]
			object: object];
}

#ifdef OF_OBJFW_RUNTIME
static id
method_not_found_handler(id obj, SEL sel, ...)
{
	fprintf(stderr, "Runtime error: Selector %s is not implemented in "
	    "class %s!\n", sel_getName(sel),
	    class_getName(object_getClass(obj)));
	abort();
}

static IMP
forward_handler(id obj, SEL sel)
{
	if (class_isMetaClass(object_getClass(obj))) {
		if (![obj respondsToSelector: @selector(resolveClassMethod:)])
			return method_not_found_handler;

		if (![obj resolveClassMethod: sel])
			return method_not_found_handler;

		if (![obj respondsToSelector: sel]) {
			fprintf(stderr, "Runtime error: [%s "
			    "resolveClassMethod: %s] returned YES without "
			    "adding the method!\n", class_getName(obj),
			    sel_getName(sel));
			abort();
		}
	} else {
		Class c = object_getClass(obj);

		if (![c respondsToSelector: @selector(resolveInstanceMethod:)])
			return method_not_found_handler;

		if (![c resolveInstanceMethod: sel])
			return method_not_found_handler;

		if (![obj respondsToSelector: sel]) {
			fprintf(stderr, "Runtime error: [%s "
			    "resolveInstanceMethod: %s] returned YES without "
			    "adding the method!\n",
			    class_getName(object_getClass(obj)),
			    sel_getName(sel));
			abort();
		}
	}

	return objc_msg_lookup(obj, sel);
}
#endif

#ifndef HAVE_OBJC_ENUMERATIONMUTATION
void
objc_enumerationMutation(id object)
{
	enumeration_mutation_handler(object);
}
198
199
200
201
202
203
204




205
206
207
208
209
210
211
		abort();
	}
#endif

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaught_exception_handler);
#endif





#ifdef HAVE_OBJC_ENUMERATIONMUTATION
	objc_setEnumerationMutationHandler(enumeration_mutation_handler);
#endif

	cxx_construct = sel_registerName(".cxx_construct");
	cxx_destruct = sel_registerName(".cxx_destruct");







>
>
>
>







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
		abort();
	}
#endif

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaught_exception_handler);
#endif

#ifdef OF_OBJFW_RUNTIME
	objc_forward_handler = forward_handler;
#endif

#ifdef HAVE_OBJC_ENUMERATIONMUTATION
	objc_setEnumerationMutationHandler(enumeration_mutation_handler);
#endif

	cxx_construct = sel_registerName(".cxx_construct");
	cxx_destruct = sel_registerName(".cxx_destruct");
459
460
461
462
463
464
465










466
467
468
469
470
471
472
				withMethodFromClass: class];
		}
	}
#endif

	[self inheritMethodsFromClass: [class superclass]];
}











- init
{
	Class class;
	void (*last)(id, SEL) = NULL;

	for (class = object_getClass(self); class != Nil;







>
>
>
>
>
>
>
>
>
>







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
				withMethodFromClass: class];
		}
	}
#endif

	[self inheritMethodsFromClass: [class superclass]];
}

+ (BOOL)resolveClassMethod: (SEL)selector
{
	return NO;
}

+ (BOOL)resolveInstanceMethod: (SEL)selector
{
	return NO;
}

- init
{
	Class class;
	void (*last)(id, SEL) = NULL;

	for (class = object_getClass(self); class != Nil;