0
+@description Nu support for precompiled method handlers.
0
+@copyright Copyright (c) 2008 Neon Design Technology, Inc.
0
+Licensed under the Apache License, Version 2.0 (the "License");
0
+you may not use this file except in compliance with the License.
0
+You may obtain a copy of the License at
0
+http://www.apache.org/licenses/LICENSE-2.0
0
+Unless required by applicable law or agreed to in writing, software
0
+distributed under the License is distributed on an "AS IS" BASIS,
0
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0
+See the License for the specific language governing permissions and
0
+limitations under the License.
0
+static id collect_arguments(struct handler_description *description, va_list ap)
0
+ id arguments = [[NuCell alloc] init];
0
+ id cursor = arguments;
0
+ while((type = description->description[2+i])) {
0
+ [cursor setCdr:[[[NuCell alloc] init] autorelease]];
0
+ cursor = [cursor cdr];
0
+ //NSLog(@"argument type %d: %s", i, type);
0
+ if (!strcmp(type, "@")) {
0
+ [cursor setCar:va_arg(ap, id)];
0
+ else if (!strcmp(type, "i")) {
0
+ int x = va_arg(ap, int);
0
+ [cursor setCar:get_nu_value_from_objc_value(&x, type)];
0
+ else if (!strcmp(type, "f")) {
0
+ // calling this w/ float crashes on intel
0
+ double x = (double) va_arg(ap, double);
0
+ //NSLog(@"argument is %f", *((float *) &x));
0
+ ap = ap - sizeof(float); // messy, messy...
0
+ [cursor setCar:get_nu_value_from_objc_value(&x, type)];
0
+ else if (!strcmp(type, "d")) {
0
+ double x = va_arg(ap, double);
0
+ //NSLog(@"argument is %lf", x);
0
+ [cursor setCar:get_nu_value_from_objc_value(&x, type)];
0
+ else if (!strcmp(type, "^@")) {
0
+ void *x = va_arg(ap, void *);
0
+ //NSLog(@"argument is %lf", x);
0
+ [cursor setCar:get_nu_value_from_objc_value(&x, type)];
0
+ NSLog(@"unsupported argument type %s, see objc/handler.m to add support for it", type);
0
+// helper function called by method handlers
0
+void nu_handler(void *return_value, struct handler_description *description, id receiver, va_list ap)
0
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
0
+ id arguments = collect_arguments(description, ap);
0
+ NuBlock *block = (NuBlock *) description->description[1];
0
+ id result = [block evalWithArguments:[arguments cdr] context:nil self:receiver];
0
+ if (description->description[0][1] == '@') {
0
+ if (description->description[0][0] == '!') {
0
+ set_objc_value_from_nu_value(return_value, result, description->description[0]+1);
0
+ if (description->description[0][1] == '@') {
0
+@interface NuHandlers : NSObject
0
+ struct handler_description *handlers;
0
+ int next_free_handler;
0
+@implementation NuHandlers
0
+- (id) initWithHandlers:(struct handler_description *) h count:(int) count
0
+ handler_count = count;
0
+ next_free_handler = 0;
0
+static NSMutableDictionary *handlerWarehouse = nil;
0
+@implementation NuHandlerWarehouse
0
++ (void) registerHandlers:(struct handler_description *) description withCount:(int) count forReturnType:(NSString *) returnType
0
+ if (!handlerWarehouse) {
0
+ handlerWarehouse = [[NSMutableDictionary alloc] init];
0
+ NuHandlers *handlers = [[NuHandlers alloc] initWithHandlers:description count:count];
0
+ [handlerWarehouse setObject:handlers forKey:returnType];
0
++ (IMP) handlerWithSelector:(SEL)sel block:(NuBlock *)block signature:(const char *) signature userdata:(char **) userdata
0
+ if (!handlerWarehouse) {
0
+ NuHandlers *handlers =
0
+ [handlerWarehouse objectForKey:[NSString stringWithCString:userdata[0]+1 encoding:NSUTF8StringEncoding]];
0
+ if (handlers->next_free_handler < handlers->handler_count) {
0
+ handlers->handlers[handlers->next_free_handler].description = userdata;
0
+ IMP handler = handlers->handlers[handlers->next_free_handler].handler;
0
+ handlers->next_free_handler++;
Comments
No one has commented yet.