Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions ext/obj_ext/RIGSBridgeSupportParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
}
Expand Down
47 changes: 22 additions & 25 deletions ext/obj_ext/RIGSCore.m
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions ext/obj_ext/RIGSUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); })
Expand All @@ -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 */
47 changes: 36 additions & 11 deletions ext/obj_ext/RIGSUtilities.m
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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 == '"')
Expand All @@ -219,7 +246,7 @@
/* do nothing */;
}

type = objc_skip_type_qualifiers(type);
type = rb_objc_skip_type_qualifiers(type);

switch (*type) {

Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand All @@ -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:
{
Expand Down