CFArrayRef VMKXMLPathProcessorEvaluateExpression(VMKXMLPathProcessorRef processor, const char *expression) { assert(processor); xmlXPathObjectPtr xpathObject = xmlXPathEvalExpression((xmlChar *)expression, processor->_rawXMLPathContext); xmlNodeSetPtr nodes = xpathObject->nodesetval; CFMutableArrayRef results = NULL; if (nodes) { results = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); int looper = 0; while (looper < nodes->nodeNr) { VMKXMLNodeRef node = VMKXMLNodeCreate(nodes->nodeTab[looper]); CFArrayAppendValue(results, node); CFRelease(node); ++looper; } } xmlXPathFreeObject(xpathObject); CFMakeCollectable(results); return results; }
VALUE rb_singleton_class_clone(VALUE obj) { VALUE klass = RBASIC(obj)->klass; if (!RCLASS_SINGLETON(klass)) { return klass; } // Create new singleton class. VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass)); // Copy ivars. CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass); if (ivar_dict != NULL) { CFMutableDictionaryRef cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict); rb_class_ivar_set_dict(clone, cloned_ivar_dict); CFMakeCollectable(cloned_ivar_dict); } // Copy methods. rb_vm_copy_methods((Class)klass, (Class)clone); rb_singleton_class_attached(clone, obj); if (RCLASS_SUPER(clone) == rb_cRubyObject) { long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS; RCLASS_SET_VERSION(clone, v); } RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON); return clone; }
static VALUE format_message(VALUE exc) { CFMutableStringRef result = CFStringCreateMutable(NULL, 0); VALUE message = rb_vm_call(exc, sel_registerName("message"), 0, NULL); VALUE bt = rb_vm_call(exc, sel_registerName("backtrace"), 0, NULL); message = rb_check_string_type(message); const char *msg = message == Qnil ? "" : RSTRING_PTR(message); const long count = (bt != Qnil ? RARRAY_LEN(bt) : 0); if (count > 0) { for (long i = 0; i < count; i++) { const char *bte = RSTRING_PTR(RARRAY_AT(bt, i)); if (i == 0) { CFStringAppendFormat(result, NULL, CFSTR("%s: %s (%s)\n"), bte, msg, rb_class2name(*(VALUE *)exc)); } else { CFStringAppendFormat(result, NULL, CFSTR("\tfrom %s\n"), bte); } } } else { CFStringAppendFormat(result, NULL, CFSTR("%s (%s)\n"), msg, rb_class2name(*(VALUE *)exc)); } CFMakeCollectable(result); return (VALUE)result; }
__private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) { CFStringRef theString = (CFStringRef)ptr; CFStringRef result = CFStringCreateCopy(allocator, theString); if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { result = (CFStringRef)CFMakeCollectable(result); } return (const void *)result; }
CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFDataRef data) { // Do not allow magic allocator for now for mutable datas, because it // isn't remembered for proper handling later when growth of the buffer // has to occur. Boolean wasMagic = (0); CFMutableDataRef r = (CFMutableDataRef) __CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, CFDataGetBytePtr(data), CFDataGetLength(data), NULL); if (wasMagic) CFMakeCollectable(r); return r; }
VALUE rb_set_dup(VALUE rcv) { VALUE dup = (VALUE)CFSetCreateMutableCopy(NULL, 0, (CFSetRef)rcv); if (OBJ_TAINTED(rcv)) OBJ_TAINT(dup); CFMakeCollectable((CFTypeRef)dup); return dup; }
CFMutableDataRef CFDataCreateMutable(CFAllocatorRef allocator, CFIndex capacity) { // Do not allow magic allocator for now for mutable datas, because it // isn't remembered for proper handling later when growth of the buffer // has to occur. Boolean wasMagic = _CFAllocatorIsGCRefZero(allocator); if (0 == capacity) allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); CFMutableDataRef r = (CFMutableDataRef)__CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, NULL, 0, NULL); if (wasMagic) CFMakeCollectable(r); return r; }
static VALUE rb_yaml_resolver_initialize(VALUE self, SEL sel) { rb_yaml_resolver_t *resolver = RYAMLResolver(self); CFMutableDictionaryRef d = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks); GC_WB(&resolver->tags, d); CFMakeCollectable(d); return self; }
VALUE rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig) { rb_obj_init_copy(clone, 0, orig); VALUE super; if (!RCLASS_RUBY(orig)) { super = orig; rb_warn("cloning class `%s' is not supported, creating a " \ "subclass instead", rb_class2name(orig)); } else { super = RCLASS_SUPER(orig); } RCLASS_SET_SUPER(clone, super); // Copy flags. unsigned long version_flag = RCLASS_IS_RUBY_CLASS; if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) { version_flag |= RCLASS_IS_OBJECT_SUBCLASS; } if (RCLASS_MODULE(orig)) { version_flag |= RCLASS_IS_MODULE; } RCLASS_SET_VERSION(clone, version_flag); if (!class_isMetaClass((Class)clone)) { // Clear type info. RCLASS_SET_VERSION(*(Class *)clone, RCLASS_VERSION(*(Class *)clone)); } // Copy methods. rb_vm_copy_methods((Class)orig, (Class)clone); if (!class_isMetaClass((Class)orig)) { rb_vm_copy_methods(*(Class *)orig, *(Class *)clone); } // Copy ivars. CFMutableDictionaryRef orig_dict = rb_class_ivar_dict(orig); CFMutableDictionaryRef clone_dict; if (orig_dict != NULL) { clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, orig_dict); rb_class_ivar_set_dict(clone, clone_dict); CFMakeCollectable(clone_dict); } else { clone_dict = rb_class_ivar_dict_or_create(clone); } // Remove the classpath & classid (name) so that they are not // copied over the new module / class. CFDictionaryRemoveValue(clone_dict, (const void *)id_classpath); CFDictionaryRemoveValue(clone_dict, (const void *)id_classid); return clone; }
/* :nodoc: */ VALUE rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig) { static ID classpath = 0; static ID classid = 0; rb_obj_init_copy(clone, 0, orig); { VALUE super; unsigned long version_flag; if (!RCLASS_RUBY(orig)) { super = orig; rb_warn("cloning class `%s' is not supported, creating a " \ "subclass instead", rb_class2name(orig)); } else { super = RCLASS_SUPER(orig); } RCLASS_SET_SUPER(clone, super); version_flag = RCLASS_IS_RUBY_CLASS; if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) { version_flag |= RCLASS_IS_OBJECT_SUBCLASS; } RCLASS_SET_VERSION(clone, version_flag); rb_vm_copy_methods((Class)orig, (Class)clone); CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig); if (ivar_dict != NULL) { CFMutableDictionaryRef cloned_ivar_dict; if (classpath == 0) { classpath = rb_intern("__classpath__"); } if (classid == 0) { classid = rb_intern("__classid__"); } cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict); // Remove the classpath & classid (name) so that they are not // copied over the new module / class CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath); CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid); CFMakeCollectable(cloned_ivar_dict); rb_class_ivar_set_dict(clone, cloned_ivar_dict); } } return clone; }
static VALUE set_alloc(VALUE klass) { CFMutableSetRef set; set = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); if (klass != 0 && klass != rb_cNSSet && klass != rb_cNSMutableSet) *(Class *)set = (Class)klass; CFMakeCollectable(set); return (VALUE)set; }
bool bs_parser_parse(bs_parser_t *parser, const char *path, const char *framework_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; bs_element_method_t *method; unsigned int i; #define MAX_ARGS 128 bs_element_arg_t args[MAX_ARGS]; bs_element_arg_t fptr_args[MAX_ARGS]; char *protocol_name = NULL; int func_ptr_arg_depth; bs_element_function_pointer_t *func_ptr; bool success; CFStringRef cf_path; bool nested_func_ptr; unsigned int version_number = 0; if (callback == NULL) return false; /* check if the given framework path has not been loaded already */ cf_path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorMalloc, path); CFMakeCollectable(cf_path); for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths); i < count; i++) { CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i); if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { /* already loaded */ return true; } } CFArrayAppendValue(parser->loaded_paths, cf_path); //printf("parsing %s\n", path); #define BAIL(fmt, args...) \ do { \ if (error != NULL) { \ char buf[1024]; \ snprintf(buf, sizeof buf, \ "%s:%ld - "fmt, path, \ xmlGetLineNo(xmlTextReaderCurrentNode(reader)), \ ##args); \ *error = strdup(buf); \ } \ success = false; \ goto bails; \ } \ while (0) #if __LP64__ # define CHECK_TYPE_ATTRIBUTE(var) CHECK_ATTRIBUTE(var, "type") #else # define CHECK_TYPE_ATTRIBUTE(var) \ if (var == NULL && get_type64_attribute(reader) != NULL) { \ break; \ } \ CHECK_ATTRIBUTE(var, "type") #endif #define CHECK_ATTRIBUTE_CAN_BE_EMPTY(a, name) \ CHECK_ATTRIBUTE0(a, name, true) #define CHECK_ATTRIBUTE(a, name) \ CHECK_ATTRIBUTE0(a, name, false) #define CHECK_ATTRIBUTE0(a, name, can_be_empty) \ do { \ if (a == NULL) \ BAIL("expected attribute `%s' for element `%s'", \ name, xmlTextReaderConstName(reader)); \ if (!can_be_empty && *a == '\0') { \ free(a); \ BAIL("empty attribute `%s' for element `%s'", \ name, xmlTextReaderConstName(reader)); \ } \ } while (0) \ reader = xmlNewTextReaderFilename(path); if (reader == NULL) BAIL("cannot create XML text reader for file at path `%s'", path); func = NULL; func_ptr = NULL; func_ptr_arg_depth = -1; nested_func_ptr = false; klass = NULL; method = NULL; protocol_name = NULL; while (true) { const char *name; unsigned int namelen; int node_type = -1; bool eof = false; struct bs_xml_atom *atom; void *bs_element; bs_element_type_t bs_element_type = 0; do { int retval = xmlTextReaderRead(reader); if (retval == 0) { eof = true; break; } else if (retval < 0) BAIL("parsing error: %d", retval); node_type = xmlTextReaderNodeType(reader); } while (node_type != XML_READER_TYPE_ELEMENT && node_type != XML_READER_TYPE_END_ELEMENT); if (eof) break; name = (const char *)xmlTextReaderConstName(reader); namelen = strlen(name); bs_element = NULL; atom = bs_xml_element(name, namelen); if (atom == NULL) { // TODO: we should include the "signatures" string into the gperf // function. if (version_number == 0 && strcmp(name, "signatures") == 0) { char *str = get_attribute(reader, "version"); if (str != NULL) { char *p = strchr(str, '.'); if (p != NULL) { *p = '\0'; int major = atoi(str); int minor = atoi(&p[1]); assert(major < 10 && minor < 10); version_number = (major * 10) + minor; parser->version_number = version_number; } free(str); } } continue; } if (nested_func_ptr) { // FIXME: elements nesting function_pointers aren't supported yet by the // parser, so we just ignore them. if (node_type == XML_READER_TYPE_END_ELEMENT && (atom->val == BS_XML_FUNCTION || atom->val == BS_XML_METHOD)) { nested_func_ptr = false; } continue; } if (node_type == XML_READER_TYPE_ELEMENT) { switch (atom->val) { case BS_XML_DEPENDS_ON: { char *depends_on_path; char bs_path[PATH_MAX]; bool bs_path_found; depends_on_path = get_attribute(reader, "path"); CHECK_ATTRIBUTE(depends_on_path, "path"); //printf("depends of %s\n", depends_on_path); bs_path_found = bs_find_path(depends_on_path, bs_path, sizeof bs_path); if (bs_path_found) { if (!bs_parser_parse(parser, bs_path, depends_on_path, options, callback, context, error)) { free(depends_on_path); return false; } } free(depends_on_path); break; } case BS_XML_CONSTANT: { bs_element_constant_t *bs_const; char *const_name; char *const_type; const_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(const_name, "name"); const_type = get_type_attribute(reader); CHECK_TYPE_ATTRIBUTE(const_type); bs_const = (bs_element_constant_t *) malloc(sizeof(bs_element_constant_t)); ASSERT_ALLOC(bs_const); bs_const->name = const_name; bs_const->type = const_type; bs_const->ignore = false; bs_const->suggestion = NULL; bs_const->magic_cookie = get_boolean_attribute(reader, "magic_cookie", false); bs_element = bs_const; bs_element_type = BS_ELEMENT_CONSTANT; break; } case BS_XML_STRING_CONSTANT: { bs_element_string_constant_t *bs_strconst; char *strconst_name; char *strconst_value; strconst_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(strconst_name, "name"); strconst_value = get_attribute(reader, "value"); CHECK_ATTRIBUTE_CAN_BE_EMPTY(strconst_value, "value"); bs_strconst = (bs_element_string_constant_t *) malloc(sizeof(bs_element_string_constant_t)); ASSERT_ALLOC(bs_strconst); bs_strconst->name = strconst_name; bs_strconst->value = strconst_value; bs_strconst->nsstring = get_boolean_attribute(reader, "nsstring", false); bs_element = bs_strconst; bs_element_type = BS_ELEMENT_STRING_CONSTANT; break; } case BS_XML_ENUM: { char *enum_name; char *enum_value; enum_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(enum_name, "name"); #if __LP64__ enum_value = get_attribute(reader, "value64"); if (enum_value == NULL) #endif enum_value = get_attribute(reader, "value"); #if BYTE_ORDER == BIG_ENDIAN # define BYTE_ORDER_VALUE_ATTR_NAME "be_value" #else # define BYTE_ORDER_VALUE_ATTR_NAME "le_value" #endif if (enum_value == NULL) enum_value = get_attribute(reader, BYTE_ORDER_VALUE_ATTR_NAME); if (enum_value != NULL) { bs_element_enum_t *bs_enum; bs_enum = (bs_element_enum_t *)malloc(sizeof(bs_element_enum_t)); ASSERT_ALLOC(bs_enum); bs_enum->name = enum_name; bs_enum->value = enum_value; bs_enum->ignore = get_boolean_attribute(reader, "ignore", false); bs_enum->suggestion = get_attribute(reader, "suggestion"); bs_element = bs_enum; bs_element_type = BS_ELEMENT_ENUM; } break; } case BS_XML_STRUCT: { bs_element_struct_t *bs_struct; char *struct_decorated_type; char *struct_name; char type[MAX_ENCODE_LEN]; bs_element_struct_field_t fields[128]; int field_count; struct_decorated_type = get_type_attribute(reader); CHECK_TYPE_ATTRIBUTE(struct_decorated_type); struct_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(struct_name, "name"); if (!undecorate_struct_type(struct_decorated_type, type, sizeof type, fields, 128, &field_count)) { BAIL("Can't handle structure '%s' with type '%s'", struct_name, struct_decorated_type); } free(struct_decorated_type); bs_struct = (bs_element_struct_t *)malloc(sizeof(bs_element_struct_t)); ASSERT_ALLOC(bs_struct); bs_struct->name = struct_name; bs_struct->type = strdup(type); bs_struct->fields = (bs_element_struct_field_t *)malloc( sizeof(bs_element_struct_field_t) * field_count); ASSERT_ALLOC(bs_struct->fields); memcpy(bs_struct->fields, fields, sizeof(bs_element_struct_field_t) * field_count); bs_struct->fields_count = field_count; bs_struct->opaque = get_boolean_attribute(reader, "opaque", false); bs_element = bs_struct; bs_element_type = BS_ELEMENT_STRUCT; break; } case BS_XML_OPAQUE: { bs_element_opaque_t *bs_opaque; char *opaque_name; char *opaque_type; opaque_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(opaque_name, "name"); opaque_type = get_type_attribute(reader); CHECK_TYPE_ATTRIBUTE(opaque_type); bs_opaque = (bs_element_opaque_t *)malloc(sizeof(bs_element_opaque_t)); ASSERT_ALLOC(bs_opaque); bs_opaque->name = opaque_name; bs_opaque->type = opaque_type; bs_element = bs_opaque; bs_element_type = BS_ELEMENT_OPAQUE; break; } case BS_XML_CFTYPE: { bs_element_cftype_t *bs_cftype; char *cftype_name; char *cftype_type; cftype_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(cftype_name, "name"); cftype_type = get_type_attribute(reader); CHECK_TYPE_ATTRIBUTE(cftype_type); bs_cftype = (bs_element_cftype_t *)malloc(sizeof(bs_element_cftype_t)); ASSERT_ALLOC(bs_cftype); bs_cftype->name = cftype_name; bs_cftype->type = cftype_type; #if 1 /* the type_id field isn't used in MacRuby */ bs_cftype->type_id = 0; #else char *cftype_gettypeid_func_name; cftype_gettypeid_func_name = get_attribute(reader, "gettypeid_func"); if (cftype_gettypeid_func_name != NULL) { void *sym; sym = dlsym(RTLD_DEFAULT, cftype_gettypeid_func_name); if (sym == NULL) { BAIL("cannot locate gettypeid_func function `%s'", cftype_gettypeid_func_name); } else { CFTypeID (*cb)(void) = sym; bs_cftype->type_id = (*cb)(); } } else { bs_cftype->type_id = 0; } #endif bs_cftype->tollfree = get_attribute(reader, "tollfree"); bs_element = bs_cftype; bs_element_type = BS_ELEMENT_CFTYPE; break; } case BS_XML_INFORMAL_PROTOCOL: { if (protocol_name != NULL) free(protocol_name); protocol_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(protocol_name, "name"); break; } case BS_XML_FUNCTION: { char *func_name; func_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(func_name, "name"); func = (bs_element_function_t *)malloc(sizeof(bs_element_function_t)); ASSERT_ALLOC(func); func->name = func_name; func->variadic = get_boolean_attribute(reader, "variadic", false); func->args_count = 0; func->args = NULL; func->retval = NULL; if (xmlTextReaderIsEmptyElement(reader)) { bs_element = func; bs_element_type = BS_ELEMENT_FUNCTION; func = NULL; } break; } case BS_XML_FUNCTION_ALIAS: { bs_element_function_alias_t *bs_func_alias; char *alias_name; char *alias_original; alias_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(alias_name, "name"); alias_original = get_attribute(reader, "original"); CHECK_ATTRIBUTE(alias_original, "original"); bs_func_alias = (bs_element_function_alias_t *)malloc( sizeof(bs_element_function_alias_t)); ASSERT_ALLOC(bs_func_alias); bs_func_alias->name = alias_name; bs_func_alias->original = alias_original; bs_element = bs_func_alias; bs_element_type = BS_ELEMENT_FUNCTION_ALIAS; break; } case BS_XML_CLASS: { char *class_name; class_name = get_attribute(reader, "name"); CHECK_ATTRIBUTE(class_name, "name"); klass = (bs_element_class_t *)malloc(sizeof(bs_element_class_t)); ASSERT_ALLOC(klass); klass->name = class_name; klass->class_methods = klass->instance_methods = NULL; klass->class_methods_count = klass->instance_methods_count = 0; break; } case BS_XML_ARG: { if (func != NULL || method != NULL || func_ptr != NULL) { bs_element_arg_t *bs_arg; unsigned *argc; argc = func_ptr != NULL ? &func_ptr->args_count : func != NULL ? &func->args_count : &method->args_count; if (*argc >= MAX_ARGS) { if (func_ptr != NULL) BAIL("maximum number of arguments (%d) reached " \ "for function pointer", MAX_ARGS); else if (func != NULL) BAIL("maximum number of arguments (%d) reached " \ "for function '%s'", MAX_ARGS, func->name); else BAIL("maximum number of arguments (%d) reached " \ "for method '%s'", MAX_ARGS, (char *)method->name); } bs_element_arg_t *args_from = (func_ptr == NULL ? args : fptr_args); bs_arg = &args_from[(*argc)++]; if (method != NULL && func_ptr == NULL) { char *index = get_attribute(reader, "index"); CHECK_ATTRIBUTE(index, "index"); bs_arg->index = strtol(index, NULL, 10); free(index); } else { bs_arg->index = -1; } get_type_modifier_attribute(reader, &bs_arg->type_modifier); #if __LP64__ bs_arg->sel_of_type = get_attribute(reader, "sel_of_type64"); if (bs_arg->sel_of_type == NULL) #endif bs_arg->sel_of_type = get_attribute(reader, "sel_of_type"); bs_arg->printf_format = get_boolean_attribute(reader, "printf_format", false); bs_arg->null_accepted = get_boolean_attribute(reader, "null_accepted", true); get_c_ary_type_attribute(reader, &bs_arg->carray_type, &bs_arg->carray_type_value); bs_arg->type = get_type_attribute(reader); if (get_boolean_attribute(reader, "function_pointer", false)) { if (func_ptr != NULL) { func_ptr = NULL; nested_func_ptr = true; break; } bs_arg->function_pointer = (bs_element_function_pointer_t *) calloc(1, sizeof(bs_element_function_pointer_t)); ASSERT_ALLOC(bs_arg->function_pointer); func_ptr = bs_arg->function_pointer; func_ptr_arg_depth = xmlTextReaderDepth(reader); } else { bs_arg->function_pointer = NULL; } } else { BAIL("argument defined outside of a " \ "function/method/function_pointer"); } break; } case BS_XML_RETVAL: { if (func != NULL || method != NULL || func_ptr != NULL) { bs_element_retval_t *bs_retval; if (func_ptr != NULL) { if (func_ptr->retval != NULL) BAIL("function pointer return value defined more than once"); } else if (func != NULL) { if (func->retval != NULL) BAIL("function '%s' return value defined more than once", func->name); } else if (method != NULL) { if (method->retval != NULL) BAIL("method '%s' return value defined more than once", (char *)method->name); } bs_retval = (bs_element_retval_t *)malloc(sizeof(bs_element_retval_t)); ASSERT_ALLOC(bs_retval); get_c_ary_type_attribute(reader, &bs_retval->carray_type, &bs_retval->carray_type_value); bs_retval->type = get_type_attribute(reader); if (bs_retval->type != NULL) bs_retval->already_retained = get_boolean_attribute(reader, "already_retained", false); if (func_ptr != NULL) { if (bs_retval->type != NULL) { func_ptr->retval = bs_retval; } else { free(bs_retval); BAIL("function pointer return value defined without type"); } } else if (func != NULL) { if (bs_retval->type != NULL) { func->retval = bs_retval; } else { free(bs_retval); #if !defined(__LP64__) if (get_type64_attribute(reader) != NULL) { // The function has no 32-bit return value type and we // run in 32-bit mode. We just ignore it. func = NULL; break; } #endif BAIL("function '%s' return value defined without type", func->name); } } else { method->retval = bs_retval; } if (get_boolean_attribute(reader, "function_pointer", false)) { if (func_ptr != NULL) { func_ptr = NULL; nested_func_ptr = true; break; } bs_retval->function_pointer = (bs_element_function_pointer_t *) calloc(1, sizeof(bs_element_function_pointer_t)); ASSERT_ALLOC(bs_retval->function_pointer); func_ptr = bs_retval->function_pointer; func_ptr_arg_depth = xmlTextReaderDepth(reader); } else { bs_retval->function_pointer = NULL; } } else { BAIL("return value defined outside a function/method"); } break; } case BS_XML_METHOD: { if (protocol_name != NULL) { bs_element_informal_protocol_method_t *bs_informal_method; char *selector; char *method_type; selector = get_attribute(reader, "selector"); CHECK_ATTRIBUTE(selector, "selector"); method_type = get_type_attribute(reader); CHECK_TYPE_ATTRIBUTE(method_type); bs_informal_method = (bs_element_informal_protocol_method_t *) malloc(sizeof(bs_element_informal_protocol_method_t)); ASSERT_ALLOC(bs_informal_method); bs_informal_method->name = sel_registerName(selector); free(selector); bs_informal_method->class_method = get_boolean_attribute(reader, "class_method", false); bs_informal_method->type = method_type; bs_informal_method->protocol_name = strdup(protocol_name); bs_element = bs_informal_method; bs_element_type = BS_ELEMENT_INFORMAL_PROTOCOL_METHOD; } else if (klass != NULL) { char *selector; selector = get_attribute(reader, "selector"); CHECK_ATTRIBUTE(selector, "selector"); method = (bs_element_method_t *)malloc(sizeof(bs_element_method_t)); ASSERT_ALLOC(method); method->name = sel_registerName(selector); free(selector); method->class_method = get_boolean_attribute(reader, "class_method", false); method->variadic = get_boolean_attribute(reader, "variadic", false); method->ignore = get_boolean_attribute(reader, "ignore", false); method->suggestion = get_attribute(reader, "suggestion"); method->args_count = 0; method->args = NULL; method->retval = NULL; if (xmlTextReaderIsEmptyElement(reader)) { goto index_method; } } else { BAIL("method defined outside a class or informal protocol"); } break; } } } else if (node_type == XML_READER_TYPE_END_ELEMENT) { switch (atom->val) { case BS_XML_INFORMAL_PROTOCOL: { protocol_name = NULL; break; } case BS_XML_RETVAL: case BS_XML_ARG: { if (func_ptr != NULL && func_ptr_arg_depth == xmlTextReaderDepth(reader)) { bs_element_retval_t *retval = NULL; bs_element_arg_t *arg = NULL; unsigned args_count; if (atom->val == BS_XML_RETVAL) { retval = func != NULL ? func->retval : method->retval; } else { args_count = func != NULL ? func->args_count : method->args_count; arg = &args[args_count - 1]; } // Determine if we deal with a block or a function pointer. const char *old_type = (retval ? retval->type : arg->type); const char lambda_type = *old_type == '@' ? _MR_C_LAMBDA_BLOCK : _MR_C_LAMBDA_FUNCPTR; char tmp_type[1025]; // 3 less to fit <, type and > char new_type[1028]; // Function ptr return type strlcpy(tmp_type, func_ptr->retval->type, sizeof(tmp_type)); // Function ptr args for (i = 0; i < func_ptr->args_count; i++) { strlcat(tmp_type, fptr_args[i].type, sizeof(tmp_type)); } // Clear the final type string memset(new_type, 0, sizeof(new_type)); // Append the function pointer type snprintf(new_type, sizeof(new_type), "%c%c%s%c", _MR_C_LAMBDA_B, lambda_type, tmp_type, _MR_C_LAMBDA_E); // Free the old values if (retval) { free(retval->type); retval->type = strdup(new_type); } else { free(arg->type); arg->type = strdup(new_type); } if (func_ptr->args_count > 0) { size_t len; len = sizeof(bs_element_arg_t) * func_ptr->args_count; func_ptr->args = (bs_element_arg_t *)malloc(len); ASSERT_ALLOC(func_ptr->args); memcpy(func_ptr->args, fptr_args, len); } else { func_ptr->args = NULL; } func_ptr = NULL; func_ptr_arg_depth = -1; } break; } case BS_XML_FUNCTION: { if (func == NULL) { break; } for (i = 0; i < func->args_count; i++) { if (args[i].type == NULL) BAIL("function '%s' argument #%d type not provided", func->name, i); } if (func->args_count > 0) { size_t len; len = sizeof(bs_element_arg_t) * func->args_count; func->args = (bs_element_arg_t *)malloc(len); ASSERT_ALLOC(func->args); memcpy(func->args, args, len); } bs_element = func; bs_element_type = BS_ELEMENT_FUNCTION; func = NULL; break; } case BS_XML_METHOD: { bs_element_method_t *methods; unsigned *methods_count; if (method->args_count > 0) { size_t len; len = sizeof(bs_element_arg_t) * method->args_count; method->args = (bs_element_arg_t *)malloc(len); ASSERT_ALLOC(method->args); memcpy(method->args, args, len); } index_method: methods = method->class_method ? klass->class_methods : klass->instance_methods; methods_count = method->class_method ? &klass->class_methods_count : &klass->instance_methods_count; if (methods == NULL) { methods = (bs_element_method_t *)malloc( sizeof(bs_element_method_t) * (*methods_count + 1)); } else { methods = (bs_element_method_t *)realloc(methods, sizeof(bs_element_method_t) * (*methods_count + 1)); } ASSERT_ALLOC(methods); // methods[*methods_count] = method; // FIXME this is inefficient memcpy(&methods[*methods_count], method, sizeof(bs_element_method_t)); (*methods_count)++; if (method->class_method) klass->class_methods = methods; else klass->instance_methods = methods; free(method); method = NULL; break; } case BS_XML_CLASS: { bs_element = klass; bs_element_type = BS_ELEMENT_CLASS; klass = NULL; break; } } } if (bs_element != NULL) (*callback)(parser, path, bs_element_type, bs_element, context); } success = true; bails: if (protocol_name != NULL) free(protocol_name); xmlFreeTextReader(reader); if (!success) { for (unsigned i = 0, count = CFArrayGetCount(parser->loaded_paths); i < count; i++) { CFStringRef s = CFArrayGetValueAtIndex(parser->loaded_paths, i); if (CFStringCompare(cf_path, s, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { CFArrayRemoveValueAtIndex(parser->loaded_paths, i); break; } } } if (success && options == BS_PARSE_OPTIONS_LOAD_DYLIBS && framework_path != NULL) { char buf[PATH_MAX]; if (_bs_find_path(framework_path, buf, sizeof buf, "dylib")) { if (dlopen(buf, RTLD_LAZY) == NULL) { if (error != NULL) { *error = dlerror(); } success = false; } } } return success; }
CGFloat *decodeValuesFromImageDictionary(CGPDFDictionaryRef dict, CGColorSpaceRef cgColorSpace, int bitsPerComponent) { CGFloat *decodeValues = NULL; CGPDFArrayRef decodeArray = NULL; if (CGPDFDictionaryGetArray(dict, "Decode", &decodeArray)) { size_t count = CGPDFArrayGetCount(decodeArray); decodeValues = malloc(sizeof(CGFloat) * count); CGPDFReal realValue; int i; for (i = 0; i < count; i++) { CGPDFArrayGetNumber(decodeArray, i, &realValue); decodeValues[i] = realValue; } } else { size_t n; int i; switch (CGColorSpaceGetModel(cgColorSpace)) { case kCGColorSpaceModelMonochrome: decodeValues = malloc(sizeof(CGFloat) * 2); decodeValues[0] = 0.0; decodeValues[1] = 1.0; break; case kCGColorSpaceModelRGB: decodeValues = malloc(sizeof(CGFloat) * 6); for (i = 0; i < 6; i++) { decodeValues[i] = i % 2 == 0 ? 0 : 1; } break; case kCGColorSpaceModelCMYK: decodeValues = malloc(sizeof(CGFloat) * 8); for (i = 0; i < 8; i++) { decodeValues[i] = i % 2 == 0 ? 0.0 : 1.0; } break; case kCGColorSpaceModelLab: // ???? break; case kCGColorSpaceModelDeviceN: n = CGColorSpaceGetNumberOfComponents(cgColorSpace) * 2; decodeValues = malloc(sizeof(CGFloat) * (n * 2)); i = 0; for (; i < n; i++) { decodeValues[i] = i % 2 == 0 ? 0.0 : 1.0; } break; case kCGColorSpaceModelIndexed: decodeValues = malloc(sizeof(CGFloat) * 2); decodeValues[0] = 0.0; decodeValues[1] = pow(2.0,(double)bitsPerComponent) - 1; break; default: break; } } return (CGFloat *)CFMakeCollectable(decodeValues); }
CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){ CGColorSpaceRef cgColorSpace = NULL, alternateColorSpace = NULL; CGPDFStreamRef stream; const char *colorSpaceName = NULL, *alternateColorSpaceName = NULL; CGPDFInteger numberOfComponents; CGPDFDictionaryRef dict; bool retrieved; CGFloat *range; CGPDFArrayRef rangeArray; if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) { if (strcmp(colorSpaceName, "ICCBased") == 0) { if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) { dict = CGPDFStreamGetDictionary(stream); // First obtain the alternate color space if present if (CGPDFDictionaryGetName(dict, "Alternate", &alternateColorSpaceName)) { if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(alternateColorSpaceName, "DeviceGray") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(alternateColorSpaceName, "DeviceCMYK") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); } } // Obtain the preferential color space CGPDFDataFormat dataFormat; CFDataRef colorSpaceDataPtr = CGPDFStreamCopyData(stream, &dataFormat); if (dataFormat == CGPDFDataFormatRaw) { CGDataProviderRef profile = CGDataProviderCreateWithCFData(colorSpaceDataPtr); retrieved = CGPDFDictionaryGetInteger(dict, "N", &numberOfComponents); // Deduce an alternate color space if we don't have one //already if (alternateColorSpace == NULL) { switch (numberOfComponents) { case 1: alternateColorSpace = CGColorSpaceCreateDeviceGray(); break; case 3: alternateColorSpace = CGColorSpaceCreateDeviceRGB(); break; case 4: alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); break; default: break; } } range = malloc(numberOfComponents * 2 * sizeof(CGFloat)); if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) { int i = 0; for (; i < numberOfComponents * 2; i += 2) { range[i] = (i % 2 == 0) ? 0.0 : 1.0; } } else { size_t count = CGPDFArrayGetCount(rangeArray); int i = 0; for (; i < count; i++) { (void)CGPDFArrayGetNumber(rangeArray, i, &range[i]); } } cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile, alternateColorSpace); CGDataProviderRelease(profile); free(range); if (cgColorSpace) { // Since we have a preferential color space, we no //longer need the hang on to the alternate color space CGColorSpaceRelease(alternateColorSpace); } else { cgColorSpace = alternateColorSpace; } } else if (dataFormat == CGPDFDataFormatJPEGEncoded) { // } else if (dataFormat == CGPDFDataFormatJPEG2000) { // } } } else if (strcmp(colorSpaceName, "Indexed") == 0) { CGColorSpaceRef baseSpace; CGPDFArrayRef base = NULL; CGPDFInteger highValue = 0; CGPDFStreamRef stream = NULL; CGPDFStringRef string; const unsigned char *chars; const char *namedColorSpaceName; if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) { baseSpace = colorSpaceFromPDFArray(base); } else if (CGPDFArrayGetName(colorSpaceArray, 1, &namedColorSpaceName)) { if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) { baseSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) { baseSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) { baseSpace = CGColorSpaceCreateDeviceCMYK(); } } retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue); if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) { chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL)); } else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) { chars = CGPDFStringGetBytePtr(string); } else { // TODO: Raise some error state? } cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue, chars); } } return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace); }