Revision: 485 http://trac.macosforge.org/projects/ruby/changeset/485 Author: lsansonetti@apple.com Date: 2008-08-26 13:17:30 -0700 (Tue, 26 Aug 2008) Log Message: ----------- introduce bs_parser_t so that we never parse the same file twice Modified Paths: -------------- MacRuby/trunk/bs.c MacRuby/trunk/bs.h MacRuby/trunk/objc.m Modified: MacRuby/trunk/bs.c =================================================================== --- MacRuby/trunk/bs.c 2008-08-26 03:23:42 UTC (rev 484) +++ MacRuby/trunk/bs.c 2008-08-26 20:17:30 UTC (rev 485) @@ -358,11 +358,34 @@ return false; } -static bool -_bs_parse(const char *path, char **loaded_paths, - bs_parse_options_t options, bs_parse_callback_t callback, - void *context, char **error) +struct _bs_parser { + CFMutableArrayRef loaded_paths; +}; + +bs_parser_t * +bs_parser_new(void) { + struct _bs_parser *parser; + + parser = (struct _bs_parser *)malloc(sizeof(struct _bs_parser)); + parser->loaded_paths = + CFArrayCreateMutable(kCFAllocatorMalloc, 0, &kCFTypeArrayCallBacks); + + return parser; +} + +void +bs_parser_free(bs_parser_t *parser) +{ + CFRelease(parser->loaded_paths); + free(parser); +} + +bool +bs_parser_parse(bs_parser_t *parser, const char *path, + bs_parse_options_t options, bs_parse_callback_t callback, + void *context, char **error) +{ xmlTextReaderPtr reader; bs_element_function_t *func; bs_element_class_t *klass; @@ -374,22 +397,19 @@ int func_ptr_arg_depth; bs_element_function_pointer_t *func_ptr; bool success; + CFStringRef cf_path; if (callback == NULL) return false; - for (i = 0; i < PATH_MAX; i++) { - char *p = loaded_paths[i]; - if (p == NULL) { - loaded_paths[i] = strdup(path); - break; - } - else if (strcmp(p, path) == 0) { - /* already loaded */ - return true; - } - } - + cf_path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorMalloc, + path); + if (CFArrayContainsValue(parser->loaded_paths, CFRangeMake(0, CFArrayGetCount(parser->loaded_paths)), cf_path)) { + /* already loaded */ + CFRelease(cf_path); + return true; + } + //printf("parsing %s\n", path); #define BAIL(fmt, args...) \ @@ -483,8 +503,8 @@ sizeof bs_path); free(depends_on_path); if (bs_path_found) { - if (!_bs_parse(bs_path, loaded_paths, options, callback, context, - error)) + if (!bs_parser_parse(parser, bs_path, options, callback, context, + error)) return false; } break; @@ -1087,7 +1107,7 @@ } if (bs_element != NULL) - (*callback)(path, bs_element_type, bs_element, context); + (*callback)(parser, path, bs_element_type, bs_element, context); } success = true; @@ -1098,6 +1118,11 @@ xmlFreeTextReader(reader); + if (success) { + CFArrayAppendValue(parser->loaded_paths, cf_path); + } + CFRelease(cf_path); + if (success && options == BS_PARSE_OPTIONS_LOAD_DYLIBS) { char *p, buf[PATH_MAX]; strncpy(buf, path, sizeof buf); @@ -1115,26 +1140,6 @@ return success; } -bool -bs_parse(const char *path, bs_parse_options_t options, - bs_parse_callback_t callback, void *context, char **error) -{ - char **loaded_paths; - bool status; - unsigned i; - - loaded_paths = (char **)alloca(sizeof(char *) * PATH_MAX); - ASSERT_ALLOC(loaded_paths); - memset(loaded_paths, 0, PATH_MAX); - - status = _bs_parse(path, loaded_paths, options, callback, context, error); - - for (i = 0; i < PATH_MAX && loaded_paths[i] != NULL; i++) - free(loaded_paths[i]); - - return status; -} - #define SAFE_FREE(x) do { if ((x) != NULL) free(x); } while (0) static void bs_free_retval(bs_element_retval_t *bs_retval); @@ -1295,55 +1300,3 @@ } free(value); } - -#if 0 -struct bs_register_entry { - bs_parse_callback_t *callback; - void *context; -}; - -static struct bs_register_entry **bs_register_entries = NULL; -static unsigned bs_register_entries_count = 0; -static bs_register_token_t tokens = 0; - -bs_register_token_t -bs_register(bs_parse_callback_t *callback, void *context) -{ - struct bs_register_entry *entry; - - entry = (struct bs_register_entry *)malloc(sizeof(struct bs_register_entry)); - ASSERT_ALLOC(entry); - - entry->callback = callback; - entry->context = context; - - if (bs_register_entries == NULL) { - assert(bs_register_entries_count == 0); - bs_register_entries = (struct bs_register_entry **) - malloc(sizeof(struct bs_register_entry *)); - } - else { - assert(bs_register_entries_count > 0); - - } -} -#endif - -bs_register_token_t -bs_register(bs_parse_callback_t *callback, void *context) -{ - /* TODO */ - return 1; -} - -void -bs_unregister(bs_register_token_t token) -{ - /* TODO */ -} - -void -bs_notify(bs_element_type_t type, void *value) -{ - /* TODO */ -} Modified: MacRuby/trunk/bs.h =================================================================== --- MacRuby/trunk/bs.h 2008-08-26 03:23:42 UTC (rev 484) +++ MacRuby/trunk/bs.h 2008-08-26 20:17:30 UTC (rev 485) @@ -198,8 +198,23 @@ */ bool bs_find_path(const char *framework_path, char *path, const size_t path_len); +/* bs_parser_new() + * + * Creates and returns a parser object, required for bs_parser_parse(). + * Use bs_parser_free() when you're done. + */ +typedef struct _bs_parser bs_parser_t; +bs_parser_t *bs_parser_new(void); + +/* bs_parser_free() + * + * Frees a previously-created parser object. + */ +void bs_parser_free(bs_parser_t *parser); + typedef void (*bs_parse_callback_t) - (const char *path, bs_element_type_t type, void *value, void *context); + (bs_parser_t *parser, const char *path, bs_element_type_t type, void *value, + void *context); typedef enum { /* Default option: parse bridge support files. */ @@ -215,6 +230,7 @@ * to the callback function, using bs_element_free(). * Returns true on success, otherwise false. * + * parser: the parser object. * path: the full path of the bridge support file to parse. * options: parsing options. * callback: a callback function pointer. @@ -224,8 +240,9 @@ * allocated error message. You are responsible to free it. Pass NULL if you * don't need it. */ -bool bs_parse(const char *path, bs_parse_options_t options, - bs_parse_callback_t callback, void *context, char **error); +bool bs_parser_parse(bs_parser_t *parser, const char *path, + bs_parse_options_t options, bs_parse_callback_t callback, void *context, + char **error); /* bs_element_free() * @@ -237,42 +254,4 @@ */ void bs_element_free(bs_element_type_t type, void *value); -typedef unsigned bs_register_token_t; - -/* bs_register() - * - * Registers an asynchronous callback that will be called by bs_notify(). - * This function is meant to be called by scripting language bridges, to - * register themselves for future notifications by frameworks that dynamically - * generate APIs. You are responsible to free every element passed to the - * callback function, using bs_element_free(). - * Returns a token identifier that can be passed to bs_unregister() to - * unregister the callback. - * - * callback: a callback function pointer. - * context: a contextual data pointer that will be passed to the callback - * function. -*/ -bs_register_token_t bs_register(bs_parse_callback_t *callback, void *context); - -/* bs_unregister() - * - * Unregisters a previously-registered callback. - * - * token: a token that was returned by bs_register(). - */ -void bs_unregister(bs_register_token_t token); - -/* bs_notify() - * - * Notifies all clients registered through bs_register() that a new bridge - * support element is available. This function is meant to be called by - * frameworks that generate APIs at runtime. - * - * type: the type of the bridge support element. - * value: a pointer to the bridge support element. The element should be - * entierely composed of memory allocated by malloc(3). - */ -void bs_notify(bs_element_type_t type, void *value); - #endif /* __BS_H_ */ Modified: MacRuby/trunk/objc.m =================================================================== --- MacRuby/trunk/objc.m 2008-08-26 03:23:42 UTC (rev 484) +++ MacRuby/trunk/objc.m 2008-08-26 20:17:30 UTC (rev 485) @@ -2169,16 +2169,12 @@ } static void -bs_parse_cb(const char *path, bs_element_type_t type, void *value, void *ctx) +bs_parse_cb(bs_parser_t *parser, const char *path, bs_element_type_t type, + void *value, void *ctx) { bool do_not_free = false; - static CFMutableDictionaryRef rb_cObject_dict = NULL; + CFMutableDictionaryRef rb_cObject_dict = (CFMutableDictionaryRef)ctx; - if (rb_cObject_dict == NULL) { - rb_cObject_dict = rb_class_ivar_dict(rb_cObject); - assert(rb_cObject_dict != NULL); - } - switch (type) { case BS_ELEMENT_ENUM: { @@ -2359,27 +2355,47 @@ bs_element_free(type, value); } -static VALUE -rb_objc_load_bs(VALUE recv, VALUE path) +extern VALUE enable_method_added; + +static bs_parser_t *bs_parser = NULL; + +static void +rb_objc_load_bridge_support(const char *path, int options) { char *error; + bool ok; + CFMutableDictionaryRef rb_cObject_dict; - if (!bs_parse(StringValuePtr(path), 0, bs_parse_cb, NULL, &error)) + if (bs_parser == NULL) { + bs_parser = bs_parser_new(); + } + + rb_cObject_dict = rb_class_ivar_dict(rb_cObject); + assert(rb_cObject_dict != NULL); + + enable_method_added = Qfalse; + ok = bs_parser_parse(bs_parser, path, options, + bs_parse_cb, rb_cObject_dict, &error); + enable_method_added = Qtrue; + if (!ok) { rb_raise(rb_eRuntimeError, error); + } +} +static VALUE +rb_objc_load_bs(VALUE recv, VALUE path) +{ + rb_objc_load_bridge_support(StringValuePtr(path), 0); return recv; } static void -load_bridge_support(const char *framework_path) +rb_objc_search_and_load_bridge_support(const char *framework_path) { char path[PATH_MAX]; - char *error; if (bs_find_path(framework_path, path, sizeof path)) { - if (!bs_parse(path, BS_PARSE_OPTIONS_LOAD_DYLIBS, bs_parse_cb, NULL, - &error)) - rb_raise(rb_eRuntimeError, error); + rb_objc_load_bridge_support(path, BS_PARSE_OPTIONS_LOAD_DYLIBS); } } @@ -2505,7 +2521,7 @@ [[error description] UTF8String]); } - load_bridge_support(cstr); + rb_objc_search_and_load_bridge_support(cstr); reload_class_constants(); return Qtrue;
participants (1)
-
source_changes@macosforge.org