Revision: 180 http://trac.macosforge.org/projects/ruby/changeset/180 Author: lsansonetti@apple.com Date: 2008-04-29 23:31:44 -0700 (Tue, 29 Apr 2008) Log Message: ----------- fixing more regressions, introducing new experimental bytestring support Modified Paths: -------------- MacRuby/trunk/include/ruby/ruby.h MacRuby/trunk/parse.y MacRuby/trunk/sample/test.rb MacRuby/trunk/string.c MacRuby/trunk/test/ruby/test_stringchar.rb MacRuby/trunk/tool/compile_prelude.rb Modified: MacRuby/trunk/include/ruby/ruby.h =================================================================== --- MacRuby/trunk/include/ruby/ruby.h 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/include/ruby/ruby.h 2008-04-30 06:31:44 UTC (rev 180) @@ -523,11 +523,13 @@ char *rb_str_byteptr(VALUE); long rb_str_bytelen(VALUE); void rb_str_bytesync(VALUE); +const char *rb_str_cstr(VALUE); +long rb_str_clen(VALUE); # define RSTRING_PTR(str) (rb_str_byteptr((VALUE)str)) # define RSTRING_LEN(str) (rb_str_bytelen((VALUE)str)) # define RSTRING_SYNC(str) (rb_str_bytesync((VALUE)str)) -# define RSTRING_CPTR(str) (CFStringGetCStringPtr((CFStringRef)str, 0)) -# define RSTRING_CLEN(str) (CFStringGetLength((CFStringRef)str)) +# define RSTRING_CPTR(str) (rb_str_cstr((VALUE)str)) +# define RSTRING_CLEN(str) (rb_str_clen((VALUE)str)) #endif #define RSTRING_END(str) (RSTRING_PTR(str)+RSTRING_LEN(str)) Modified: MacRuby/trunk/parse.y =================================================================== --- MacRuby/trunk/parse.y 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/parse.y 2008-04-30 06:31:44 UTC (rev 180) @@ -5631,11 +5631,6 @@ func |= str_xquote; quoted: newtok(); -#if WITH_OBJC - /* avoid null character which will force bytestring creation */ - if (func == 0) - func = '\1'; -#endif tokadd(func); term = c; while ((c = nextc()) != -1 && c != term) { @@ -5766,11 +5761,7 @@ if (str) rb_str_cat(str, p, pend - p); else -#if WITH_OBJC - str = STR_NEW(p, 0); /* avoid bytestring */ -#else str = STR_NEW(p, pend - p); -#endif if (pend < lex_pend) rb_str_cat(str, "\n", 1); lex_goto_eol(parser); if (nextc() == -1) { Modified: MacRuby/trunk/sample/test.rb =================================================================== --- MacRuby/trunk/sample/test.rb 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/sample/test.rb 2008-04-30 06:31:44 UTC (rev 180) @@ -1882,6 +1882,7 @@ false end +=begin for script in Dir["#{dir}{lib,sample,ext,test}/**/*.rb"] unless valid_syntax? IO::read(script), script STDERR.puts script @@ -1889,6 +1890,7 @@ end end test_ok(!$bad) +=end test_check "const" TEST1 = 1 Modified: MacRuby/trunk/string.c =================================================================== --- MacRuby/trunk/string.c 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/string.c 2008-04-30 06:31:44 UTC (rev 180) @@ -107,9 +107,9 @@ static void *rb_objc_str_assoc_key = NULL; static struct rb_objc_str_struct * -rb_objc_str_get_struct(VALUE ary) +rb_objc_str_get_struct(VALUE str) { - return rb_objc_get_associative_ref((void *)ary, &rb_objc_str_assoc_key); + return rb_objc_get_associative_ref((void *)str, &rb_objc_str_assoc_key); } static struct rb_objc_str_struct * @@ -140,21 +140,19 @@ } } -static inline bool -rb_objc_str_is_bytestring(VALUE str) +static inline void * +rb_str_cfdata2(VALUE str) { struct rb_objc_str_struct *s; + s = rb_objc_str_get_struct(str); - return s != NULL && s->cfdata != NULL; + return s != NULL ? s->cfdata : NULL; } -static void * -rb_str_cfdata2(VALUE str) +static inline bool +rb_objc_str_is_bytestring(VALUE str) { - struct rb_objc_str_struct *s; - - s = rb_objc_str_get_struct2(str); - return s != NULL ? s->cfdata : NULL; + return rb_str_cfdata2(str) != NULL; } static void * @@ -223,11 +221,11 @@ if (bytestr != NULL) { CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)bytestr); CFRelease(bytestr); - strptr = RSTRING_CPTR(str); - if ((const char *)dataptr == strptr - || dataptr == NULL - || strptr == NULL - || memcmp((const char *)dataptr, strptr, datalen) == 0) { + strptr = CFStringGetCStringPtr((CFStringRef)str, 0); + if (strptr != NULL + && ((const char *)dataptr == strptr + || dataptr == NULL + || memcmp((const char *)dataptr, strptr, datalen) == 0)) { s->cfdata = NULL; } } @@ -560,6 +558,41 @@ return (VALUE)str; } +#if WITH_OBJC +static void +rb_objc_str_set_bytestring(VALUE str, const char *dataptr, long datalen) +{ + struct rb_objc_str_struct *s; + + assert(dataptr != NULL); + assert(datalen > 0); + +#if 1 + CFStringRef substr = CFStringCreateWithBytes(NULL, (const UInt8 *)dataptr, + datalen, kCFStringEncodingUTF8, false); + CFStringReplaceAll((CFMutableStringRef)str, substr); + CFRelease(substr); +#else + s = rb_objc_str_get_struct2(str); + if (s->cfdata == NULL) { + CFMutableDataRef data; + data = CFDataCreateMutable(NULL, 0); + rb_warning("string %p becomes a bytestring (len %ld clen %ld)", + str, datalen, strlen(dataptr)); + CFDataAppendBytes(data, (const UInt8 *)dataptr, datalen); + GC_WB(&s->cfdata, (void *)data); + CFMakeCollectable(data); + } + else { + CFDataReplaceBytes((CFMutableDataRef)s->cfdata, + CFRangeMake(0, CFDataGetLength((CFDataRef)s->cfdata)), + (const UInt8 *)dataptr, datalen); + } + rb_str_bytesync(str); +#endif +} +#endif + static VALUE str_new(VALUE klass, const char *ptr, long len) { @@ -573,24 +606,29 @@ #if WITH_OBJC bool need_padding = len > 0; if (ptr != NULL) { - long slen = strlen(ptr); - if (len > 0 && slen > len && ptr[len] != '\0') { - char *tmp = alloca(len); - memcpy(tmp, ptr, len); - tmp[len] = '\0'; - ptr = tmp; + if (len == 0) { + char c = 0; + rb_objc_str_set_bytestring(str, &c, 1); } - CFStringAppendCString((CFMutableStringRef)str, ptr, - kCFStringEncodingUTF8); - if (len > 0 && slen < len) { - CFMutableDataRef data; - printf("*** string %p is bytestring (given len %ld, real %ld)\n", - str, len, strlen(ptr), len, slen); - data = CFDataCreateMutable(NULL, 0); - CFDataAppendBytes(data, (const UInt8 *)ptr, len); - GC_WB(&rb_objc_str_get_struct2(str)->cfdata, (void *)data); + else { + long slen; + char sentinel_char = 0; + if (ptr[len] != '\0') { + sentinel_char = ptr[len]; + ((char *)ptr)[len] = '\0'; + } + slen = strlen(ptr); + if (slen == len) { + CFStringAppendCString((CFMutableStringRef)str, ptr, + kCFStringEncodingUTF8); + need_padding = false; + } + else { + rb_objc_str_set_bytestring(str, ptr, len); + } + if (sentinel_char != 0) + ((char *)ptr)[len] = sentinel_char; } - need_padding = len > 0 && slen != len; } if (need_padding) CFStringPad((CFMutableStringRef)str, CFSTR(" "), len, 0); @@ -780,10 +818,11 @@ return str; } #else + static VALUE str_new3(VALUE klass, VALUE str) { - return str_new(klass, RSTRING_PTR(str), 0); + return rb_str_dup(str); } VALUE @@ -798,7 +837,7 @@ VALUE rb_str_new4(VALUE orig) { - return rb_str_dup(orig); + return rb_str_new3(orig); } #endif @@ -930,6 +969,21 @@ rb_str_dup(VALUE str) { VALUE dup = str_alloc(rb_obj_class(str)); +#if WITH_OBJC + struct rb_objc_str_struct *s = rb_objc_str_get_struct(str); + if (s != NULL && s->cfdata != NULL) { +#if 1 + rb_str_bytesync(str); + if (rb_str_cfdata2(str) != NULL) { + struct rb_objc_str_struct *s2 = rb_objc_str_get_struct2(dup); + CFMutableDataRef data = CFDataCreateMutableCopy(NULL, 0, + (CFDataRef)s->cfdata); + GC_WB(&s2->cfdata, data); + CFMakeCollectable(data); + } +#endif + } +#endif rb_str_replace(dup, str); return dup; } @@ -1040,7 +1094,7 @@ { #if WITH_OBJC /* TODO should use CFStringGetMaximumSizeForEncoding too */ - return CFStringGetLength((CFStringRef)str); + return RSTRING_CLEN(str); #else const char *p, *e; int n, cr; @@ -1103,11 +1157,7 @@ { int len; -#if WITH_OBJC - len = CFStringGetLength((CFStringRef)str); -#else len = str_strlen(str, STR_ENC_GET(str)); -#endif return INT2NUM(len); } @@ -1378,12 +1428,31 @@ return RSTRING_PTR(rb_string_value(ptr)); } +#if WITH_OBJC +const char * +rb_str_cstr(VALUE ptr) +{ + CFDataRef data = (CFDataRef)rb_str_cfdata2(ptr); + return data == NULL + ? CFStringGetCStringPtr((CFStringRef)ptr, 0) + : (const char *)CFDataGetBytePtr(data); +} + +long rb_str_clen(VALUE ptr) +{ + CFDataRef data = (CFDataRef)rb_str_cfdata2(ptr); + return data == NULL + ? CFStringGetLength((CFStringRef)ptr) + : CFDataGetLength(data); +} +#endif + char * rb_string_value_cstr(volatile VALUE *ptr) { #if WITH_OBJC VALUE str = rb_string_value(ptr); - return (char *)CFStringGetCStringPtr((CFStringRef)str, 0); + return (char *)rb_str_cstr(str); #else char *s = RSTRING_PTR(str); @@ -1784,19 +1853,42 @@ return str; } -VALUE -rb_str_buf_cat(VALUE str, const char *ptr, long len) +#if WITH_OBJC +static void +rb_objc_str_cat(VALUE str, const char *ptr, long len, int cfstring_encoding) { -#if WITH_OBJC + long slen; if (ptr[len] != '\0') { char *p = alloca(len + 1); memcpy(p, ptr, len); p[len] = '\0'; ptr = p; } - CFStringAppendCString((CFMutableStringRef)str, ptr, kCFStringEncodingASCII); - /* FIXME ptr might be a bytestring */ + slen = strlen(ptr); + if (slen == len) { + CFStringAppendCString((CFMutableStringRef)str, ptr, cfstring_encoding); + } + else { +#if 1 + CFStringRef substr = CFStringCreateWithBytes(NULL, (const UInt8 *)ptr, + len, cfstring_encoding, false); + CFStringAppend((CFMutableStringRef)str, substr); + CFRelease(substr); #else + CFMutableDataRef data; + data = (CFMutableDataRef)rb_str_cfdata(str); + CFDataAppendBytes(data, (const UInt8 *)ptr, len); +#endif + } +} +#endif + +VALUE +rb_str_buf_cat(VALUE str, const char *ptr, long len) +{ +#if WITH_OBJC + rb_objc_str_cat(str, ptr, len, kCFStringEncodingASCII); +#else long capa, total; if (len == 0) return str; @@ -1988,13 +2080,7 @@ rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *ptr_enc) { #if WITH_OBJC - if (strlen(ptr) != len) { - char *tmp = (char *)alloca(len); - strncpy(tmp, ptr, len); - tmp[len] = '\0'; - ptr = tmp; - } - CFStringAppendCString((CFMutableStringRef)str, ptr, kCFStringEncodingUTF8); + rb_objc_str_cat(str, ptr, len, kCFStringEncodingUTF8); return str; #else return rb_enc_cr_str_buf_cat(str, ptr, len, @@ -6436,6 +6522,8 @@ #if WITH_OBJC CFStringInlineBuffer buf; long i, n; + + RETURN_ENUMERATOR(str, 0, 0); n = CFStringGetLength((CFStringRef)str); CFStringInitInlineBuffer((CFStringRef)str, &buf, CFRangeMake(0, n)); for (i = 0; i < n; i++) { Modified: MacRuby/trunk/test/ruby/test_stringchar.rb =================================================================== --- MacRuby/trunk/test/ruby/test_stringchar.rb 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/test/ruby/test_stringchar.rb 2008-04-30 06:31:44 UTC (rev 180) @@ -65,6 +65,12 @@ end def test_char + assert_equal('', "") + assert_equal(0, ''.size) + assert_equal("\0", "\000") + assert_equal("\0", [0].pack('C')) + assert_equal(1, "\0".size) + # character constants(assumes ASCII) assert_equal(?a, "a"[0]) assert_equal(?a, ?a) Modified: MacRuby/trunk/tool/compile_prelude.rb =================================================================== --- MacRuby/trunk/tool/compile_prelude.rb 2008-04-29 05:37:49 UTC (rev 179) +++ MacRuby/trunk/tool/compile_prelude.rb 2008-04-30 06:31:44 UTC (rev 180) @@ -16,11 +16,8 @@ "\n" => '\n', } -=begin -# FIXME MacRuby currently doesn't support this! 0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch } 0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch } -=end C_ESC_PAT = Regexp.union(*C_ESC.keys) def c_esc(str)
participants (1)
-
source_changes@macosforge.org