Revision: 166 http://trac.macosforge.org/projects/ruby/changeset/166 Author: lsansonetti@apple.com Date: 2008-04-23 15:54:02 -0700 (Wed, 23 Apr 2008) Log Message: ----------- fixing String subclassing/metaclassing Modified Paths: -------------- MacRuby/trunk/class.c MacRuby/trunk/io.c MacRuby/trunk/string.c Modified: MacRuby/trunk/class.c =================================================================== --- MacRuby/trunk/class.c 2008-04-23 22:53:34 UTC (rev 165) +++ MacRuby/trunk/class.c 2008-04-23 22:54:02 UTC (rev 166) @@ -103,6 +103,7 @@ void rb_objc_install_array_primitives(Class); void rb_objc_install_hash_primitives(Class); +void rb_objc_install_string_primitives(Class); static VALUE rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass) @@ -148,7 +149,8 @@ if (name == NULL) FL_SET(obj, RCLASS_ANONYMOUS); - if (rb_cArray != 0 && rb_cHash != 0 && ocsuper != NULL) { + if (rb_cArray != 0 && rb_cHash != 0 && rb_cString != 0 + && ocsuper != NULL) { do { if (ocsuper == RCLASS_OCID(rb_cArray)) { rb_objc_install_array_primitives(ocklass); @@ -158,6 +160,10 @@ rb_objc_install_hash_primitives(ocklass); break; } + if (ocsuper == RCLASS_OCID(rb_cString)) { + rb_objc_install_string_primitives(ocklass); + break; + } ocsuper = class_getSuperclass(ocsuper); } while (ocsuper != NULL); Modified: MacRuby/trunk/io.c =================================================================== --- MacRuby/trunk/io.c 2008-04-23 22:53:34 UTC (rev 165) +++ MacRuby/trunk/io.c 2008-04-23 22:54:02 UTC (rev 166) @@ -798,7 +798,7 @@ return rb_funcall(io, id_write, 1, str); } io = tmp; - if (RSTRING_LEN(str) == 0) return INT2FIX(0); + if (RSTRING_CLEN(str) == 0) return INT2FIX(0); GetOpenFile(io, fptr); rb_io_check_writable(fptr); Modified: MacRuby/trunk/string.c =================================================================== --- MacRuby/trunk/string.c 2008-04-23 22:53:34 UTC (rev 165) +++ MacRuby/trunk/string.c 2008-04-23 22:54:02 UTC (rev 166) @@ -2364,6 +2364,9 @@ #endif } +#if WITH_OBJC +static bool rb_objc_str_is_pure(VALUE); +#endif /* * call-seq: @@ -2387,6 +2390,14 @@ return rb_equal(str2, str1); } #if WITH_OBJC + if (!rb_objc_str_is_pure(str2)) { + /* This is to work around a strange bug in CFEqual's objc + * dispatching. + */ + VALUE tmp = str1; + str1 = str2; + str2 = tmp; + } if (CFEqual((CFTypeRef)str1, (CFTypeRef)str2)) return Qtrue; #else @@ -4272,10 +4283,6 @@ * Returns the receiver. */ -#if WITH_OBJC -static bool rb_objc_str_is_pure(VALUE); -#endif - static VALUE rb_str_to_s(VALUE str) { @@ -7977,11 +7984,124 @@ ? __nscfstring = (Class)objc_getClass("NSCFString") \ : __nscfstring) +#define PREPARE_RCV(x) \ + Class old = *(Class *)x; \ + *(Class *)x = NSCFSTRING(); + +#define RESTORE_RCV(x) \ + *(Class *)x = old; + static bool rb_objc_str_is_pure(VALUE str) { return *(Class *)str == NSCFSTRING(); } + +static CFIndex +imp_rb_str_length(void *rcv, SEL sel) +{ + CFIndex length; + PREPARE_RCV(rcv); + length = CFStringGetLength((CFStringRef)rcv); + RESTORE_RCV(rcv); + return length; +} + +static UniChar +imp_rb_str_characterAtIndex(void *rcv, SEL sel, CFIndex idx) +{ + UniChar character; + PREPARE_RCV(rcv); + character = CFStringGetCharacterAtIndex((CFStringRef)rcv, idx); + RESTORE_RCV(rcv); + return character; +} + +static void +imp_rb_str_getCharactersRange(void *rcv, SEL sel, UniChar *buffer, + CFRange range) +{ + PREPARE_RCV(rcv); + CFStringGetCharacters((CFStringRef)rcv, range, buffer); + RESTORE_RCV(rcv); +} + +static void +imp_rb_str_replaceCharactersInRangeWithString(void *rcv, SEL sel, + CFRange range, void *str) +{ + PREPARE_RCV(rcv); + CFStringReplace((CFMutableStringRef)rcv, range, (CFStringRef)str); + RESTORE_RCV(rcv); +} + +static const UniChar * +imp_rb_str_fastCharacterContents(void *rcv, SEL sel) +{ + const UniChar *ptr; + PREPARE_RCV(rcv); + ptr = CFStringGetCharactersPtr((CFStringRef)rcv); + RESTORE_RCV(rcv); + return ptr; +} + +static const char * +imp_rb_str_fastCStringContents(void *rcv, SEL sel, bool nullTerminaisonRequired) +{ + const char *cstr; + PREPARE_RCV(rcv); + cstr = CFStringGetCStringPtr((CFStringRef)rcv, 0); + /* XXX nullTerminaisonRequired should perhaps be honored */ + RESTORE_RCV(rcv); + return cstr; +} + +static CFStringEncoding +imp_rb_str_fastestEncodingInCFStringEncoding(void *rcv, SEL sel) +{ + CFStringEncoding encoding; + PREPARE_RCV(rcv); + encoding = CFStringGetFastestEncoding((CFStringRef)rcv); + RESTORE_RCV(rcv); + return encoding; +} + +static bool +imp_rb_str_isEqual(void *rcv, SEL sel, void *other) +{ + bool flag; + PREPARE_RCV(rcv); + flag = CFEqual((CFTypeRef)rcv, (CFTypeRef)other); + RESTORE_RCV(rcv); + return flag; +} + +void +rb_objc_install_string_primitives(Class klass) +{ +#define INSTALL_METHOD(selname, imp) \ + do { \ + SEL sel = sel_registerName(selname); \ + Method method = class_getInstanceMethod(klass, sel); \ + assert(method != NULL); \ + assert(class_addMethod(klass, sel, (IMP)imp, \ + method_getTypeEncoding(method))); \ + } \ + while(0) + + INSTALL_METHOD("length", imp_rb_str_length); + INSTALL_METHOD("characterAtIndex:", imp_rb_str_characterAtIndex); + INSTALL_METHOD("getCharacters:range:", imp_rb_str_getCharactersRange); + INSTALL_METHOD("replaceCharactersInRange:withString:", + imp_rb_str_replaceCharactersInRangeWithString); + INSTALL_METHOD("_fastCharacterContents", imp_rb_str_fastCharacterContents); + INSTALL_METHOD("_fastCStringContents:", imp_rb_str_fastCStringContents); + INSTALL_METHOD("_fastestEncodingInCFStringEncoding", + imp_rb_str_fastestEncodingInCFStringEncoding); + INSTALL_METHOD("isEqual:", imp_rb_str_isEqual); + +#undef INSTALL_METHOD +} #endif /*
participants (1)
-
source_changes@macosforge.org