From f417dc9d94378c8947d301102b1873a623919cdd Mon Sep 17 00:00:00 2001 From: Ryan Krug Date: Wed, 25 Jun 2025 05:51:10 -0500 Subject: [PATCH] Move struct hash calc to Utitlties We did a struct hash calc on the struct name in a few places that we can do as a util function. We also were calculating some constants that structs to unknown or void pointers and I don't think we need them right now. --- ext/obj_ext/RIGSBridgeSupportParser.m | 22 ++++++++++--- ext/obj_ext/RIGSCore.m | 47 +++++++++++++-------------- ext/obj_ext/RIGSUtilities.h | 10 +++--- ext/obj_ext/RIGSUtilities.m | 47 ++++++++++++++++++++------- 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/ext/obj_ext/RIGSBridgeSupportParser.m b/ext/obj_ext/RIGSBridgeSupportParser.m index d53bd8e..dc4655f 100644 --- a/ext/obj_ext/RIGSBridgeSupportParser.m +++ b/ext/obj_ext/RIGSBridgeSupportParser.m @@ -177,17 +177,21 @@ - (void)parseStructWithName:(NSString*)name type:(NSString*)type { NSScanner *scanner; NSString *structKey; - NSString *arg; + NSString *argName; + NSString *argType; NSUInteger argCount; const char **args; int argIndex; + BOOL supported; // skip: "struct (unnamed at ...)" if ([name containsString:@" "]) return; - + scanner = [NSScanner scannerWithString:type]; + supported = YES; [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"{"] intoString:NULL]; + [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"_"] intoString:NULL]; [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"="] intoString:&structKey]; [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"="] intoString:NULL]; [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"}"] intoString:NULL]; @@ -198,16 +202,24 @@ - (void)parseStructWithName:(NSString*)name type:(NSString*)type argIndex = 0; while (!scanner.atEnd) { [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:NULL]; - [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:&arg]; + [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:&argName]; [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:NULL]; + [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:&argType]; [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"}"] intoString:NULL]; [scanner scanCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"}"] intoString:NULL]; - args[argIndex++] = [arg UTF8String]; + args[argIndex++] = [argName UTF8String]; + + // We don't support unknown or void pointers at this time + if ([argType isEqualToString:@"^?"] || [argType isEqualToString:@"^v"]) { + supported = NO; + } } - rb_objc_register_struct_from_objc([structKey UTF8String], [name UTF8String], args, argCount); + if (supported) { + rb_objc_register_struct_from_objc([structKey UTF8String], [name UTF8String], args, argCount); + } free(args); } diff --git a/ext/obj_ext/RIGSCore.m b/ext/obj_ext/RIGSCore.m index 736048f..045aab0 100644 --- a/ext/obj_ext/RIGSCore.m +++ b/ext/obj_ext/RIGSCore.m @@ -158,18 +158,15 @@ int inStructIndex = 0; long inStructCount = 0; - type = objc_skip_type_qualifiers(type); + type = rb_objc_skip_type_qualifiers(type); if (strcmp(type, "@?") == 0) { return &ffi_type_pointer; } if (*type == _C_STRUCT_B) { - inStructHash = HASH_SEED; - while (*type != _C_STRUCT_E && *type++ != '=') { - if (*type == '=') continue; - inStructHash = ((inStructHash << HASH_BITSHIFT) + inStructHash) + (*type); - } + inStructHash = rb_objc_hash_struct(type); + type = rb_objc_skip_type_sname(type); inStructCount = rb_array_len(rb_struct_s_members((VALUE)NSMapGet(knownStructs, (void*)inStructHash))); inStruct = (ffi_type *)malloc(sizeof(ffi_type)); @@ -180,7 +177,7 @@ while (*type != _C_STRUCT_E) { inStruct->elements[inStructIndex++] = rb_objc_ffi_type_for_type(type); - type = objc_skip_typespec(type); + type = rb_objc_skip_typespec(type); } inStruct->elements[inStructIndex] = NULL; @@ -350,9 +347,9 @@ object by calling rb_objc_release() */ if (*type == _C_STRUCT_B) { inStruct = YES; - while (*type != _C_STRUCT_E && *type++ != '='); + type = rb_objc_skip_type_sname(type); if (*type == _C_STRUCT_E) { - return; + rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into Objective-C with empty struct encoding", rb_thing); } } @@ -363,7 +360,7 @@ object by calling rb_objc_release() */ void *where; VALUE rb_val; - type = objc_skip_type_qualifiers(type); + type = rb_objc_skip_type_qualifiers(type); NSGetSizeAndAlignment(type, &tsize, &align); @@ -580,7 +577,7 @@ object by calling rb_objc_release() */ if (inStruct) { // skip the component we have just processed - type = objc_skip_typespec(type); + type = rb_objc_skip_typespec(type); } } while (inStruct && *type != _C_STRUCT_E); @@ -601,29 +598,21 @@ object by calling rb_objc_release() */ VALUE end = Qnil; if (*type == _C_STRUCT_B) { - - NSDebugLog(@"Starting conversion of ObjC structure %s to Ruby value", type); - inStruct = YES; - inStructHash = HASH_SEED; - while (*type != _C_STRUCT_E && *type++ != '=') { - if (*type == '=') continue; - inStructHash = ((inStructHash << HASH_BITSHIFT) + inStructHash) + (*type); - } + inStructHash = rb_objc_hash_struct(type); + type = rb_objc_skip_type_sname(type); if (*type == _C_STRUCT_E) { - *rb_val_ptr = Qundef; - return; + rb_raise(rb_eTypeError, "can't convert value using Objective-C encoding with empty struct into Ruby"); } } - do { VALUE rb_val; NSUInteger align; NSUInteger tsize; void *where; - type = objc_skip_type_qualifiers(type); + type = rb_objc_skip_type_qualifiers(type); NSGetSizeAndAlignment(type, &tsize, &align); @@ -650,8 +639,12 @@ object by calling rb_objc_release() */ case _C_PTR: // Assume toll-free bridge if pointer to struct + // Assume numeric if pointer to unknown or void + // Otherwise use ObjRuby::Pointer if (strncmp(type, "^{", 2) == 0) ret = rb_objc_convert_object_to_rb(where, &rb_val); + else if (strncmp(type, "^?", 2) == 0 || strncmp(type, "^v", 2) == 0) + rb_val = LL2NUM((long long) where); else rb_val = LL2NUM((long long) where); break; @@ -768,7 +761,7 @@ object by calling rb_objc_release() */ rb_ary_push(end, rb_val); } // skip the type of the component we have just processed - type = (char*)objc_skip_typespec(type); + type = (char*)rb_objc_skip_typespec(type); } else { // We are not in a C structure so simply return the // Ruby value @@ -1341,6 +1334,10 @@ object by calling rb_objc_release() */ data = dlsym(RTLD_DEFAULT, name); if (data != NULL) { + // Skip struct constants whose type is unknown to us + if (*type == _C_STRUCT_B && NSMapGet(knownStructs, (void*)rb_objc_hash_struct(type)) == NULL) { + return; + } rb_objc_convert_to_rb(data, 0, type, &rb_retval); rb_define_const(rb_mRigs, name, rb_retval); } @@ -1402,7 +1399,7 @@ object by calling rb_objc_release() */ if (NSMapGet(knownStructs, (void*)hash)) { return; } - + switch(argCount) { case 1: rb_struct = rb_struct_define_under(rb_mRigs, name, args[0], NULL); diff --git a/ext/obj_ext/RIGSUtilities.h b/ext/obj_ext/RIGSUtilities.h index d913e01..6ba6122 100644 --- a/ext/obj_ext/RIGSUtilities.h +++ b/ext/obj_ext/RIGSUtilities.h @@ -32,8 +32,6 @@ do { if (0) NSLog(fmt, ##__VA_ARGS__); } while (0) #endif -#define HASH_SEED 5381 -#define HASH_BITSHIFT 5 #define ROUND(V, A) \ ({ typeof(V) __v=(V); typeof(A) __a=(A); \ __a*((__v+__a-1)/__a); }) @@ -42,8 +40,10 @@ SEL rb_objc_method_to_sel(const char* name, int argc); char *rb_objc_sel_to_method(SEL sel); char *rb_objc_sel_to_alias(SEL sel); -unsigned long rb_objc_hash(const char* value); -const char *objc_skip_type_qualifiers (const char *type); -const char *objc_skip_typespec (const char *type); +unsigned long rb_objc_hash(const char *value); +unsigned long rb_objc_hash_struct(const char *value); +const char *rb_objc_skip_type_qualifiers(const char *type); +const char *rb_objc_skip_type_sname(const char *type); +const char *rb_objc_skip_typespec(const char *type); #endif /* __RIGSUtilitis_h_GNUSTEP_RUBY_INCLUDE */ diff --git a/ext/obj_ext/RIGSUtilities.m b/ext/obj_ext/RIGSUtilities.m index 45447d8..65d8af1 100644 --- a/ext/obj_ext/RIGSUtilities.m +++ b/ext/obj_ext/RIGSUtilities.m @@ -28,6 +28,9 @@ #import "RIGSUtilities.h" +#define HASH_SEED 5381 +#define HASH_BITSHIFT 5 + SEL rb_objc_method_to_sel(const char* name, int argc) { @@ -180,7 +183,7 @@ unsigned long -rb_objc_hash(const char* value) +rb_objc_hash(const char *value) { char keyChar; unsigned long hash = HASH_SEED; @@ -192,9 +195,26 @@ return hash; } +unsigned long +rb_objc_hash_struct(const char *value) +{ + char keyChar; + unsigned long hash = HASH_SEED; + + while ((keyChar = *value++)) { + if (keyChar == _C_STRUCT_B) continue; + if (keyChar == '_') continue; + if (keyChar == '=') break; + if (keyChar == _C_STRUCT_E) break; + hash = ((hash << HASH_BITSHIFT) + hash) + keyChar; + } + + return hash; +} + inline const char * -objc_skip_type_qualifiers(const char *type) +rb_objc_skip_type_qualifiers(const char *type) { while (*type == _C_CONST || *type == _C_IN @@ -209,8 +229,15 @@ return type; } +inline const char * +rb_objc_skip_type_sname(const char *type) +{ + while (*type != _C_STRUCT_E && *type++ != '='); + return type; +} + const char * -objc_skip_typespec(const char *type) +rb_objc_skip_typespec(const char *type) { /* Skip the variable name if any */ if (*type == '"') @@ -219,7 +246,7 @@ /* do nothing */; } - type = objc_skip_type_qualifiers(type); + type = rb_objc_skip_type_qualifiers(type); switch (*type) { @@ -263,7 +290,7 @@ while (isdigit((unsigned char)*++type)) /* do nothing */; - type = objc_skip_typespec(type); + type = rb_objc_skip_typespec(type); if (*type == _C_ARY_E) return ++type; else @@ -281,12 +308,10 @@ case _C_STRUCT_B: /* skip name, and elements until closing '}' */ - - while (*type != _C_STRUCT_E && *type++ != '=') - /* do nothing */; + type = rb_objc_skip_type_sname(type); while (*type != _C_STRUCT_E) { - type = objc_skip_typespec(type); + type = rb_objc_skip_typespec(type); } return ++type; @@ -297,14 +322,14 @@ /* do nothing */; while (*type != _C_UNION_E) { - type = objc_skip_typespec(type); + type = rb_objc_skip_typespec(type); } return ++type; case _C_PTR: /* Just skip the following typespec */ - return objc_skip_typespec(++type); + return rb_objc_skip_typespec(++type); default: {