[macruby-changes] [929] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Sun Mar 15 19:26:10 PDT 2009


Revision: 929
          http://trac.macosforge.org/projects/ruby/changeset/929
Author:   lsansonetti at apple.com
Date:     2009-03-15 19:26:09 -0700 (Sun, 15 Mar 2009)
Log Message:
-----------
removed the previous bytestring code and now use the new one

Modified Paths:
--------------
    MacRuby/branches/experimental/array.c
    MacRuby/branches/experimental/bignum.c
    MacRuby/branches/experimental/dir.c
    MacRuby/branches/experimental/encoding.c
    MacRuby/branches/experimental/file.c
    MacRuby/branches/experimental/hash.c
    MacRuby/branches/experimental/id.c
    MacRuby/branches/experimental/id.h
    MacRuby/branches/experimental/include/ruby/intern.h
    MacRuby/branches/experimental/include/ruby/ruby.h
    MacRuby/branches/experimental/io.c
    MacRuby/branches/experimental/marshal.c
    MacRuby/branches/experimental/numeric.c
    MacRuby/branches/experimental/object.c
    MacRuby/branches/experimental/pack.c
    MacRuby/branches/experimental/parse.y
    MacRuby/branches/experimental/re.c
    MacRuby/branches/experimental/ruby.c
    MacRuby/branches/experimental/string.c
    MacRuby/branches/experimental/time.c

Modified: MacRuby/branches/experimental/array.c
===================================================================
--- MacRuby/branches/experimental/array.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/array.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -45,13 +45,16 @@
 #endif
     if (mask == 0) {
 	bool _CFArrayIsMutable(void *);
-	if (!_CFArrayIsMutable((void *)ary))
+	if (!_CFArrayIsMutable((void *)ary)) {
 	    mask |= FL_FREEZE;
+	}
     }
-    if ((mask & FL_FREEZE) == FL_FREEZE)
+    if ((mask & FL_FREEZE) == FL_FREEZE) {
 	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array");
-    if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4)
+    }
+    if ((mask & FL_TAINT) == FL_TAINT && rb_safe_level() >= 4) {
 	rb_raise(rb_eSecurityError, "Insecure: can't modify array");
+    }
 }
 #define rb_ary_modify rb_ary_modify_check
 
@@ -594,9 +597,10 @@
 	return ary;
     }
     rb_ary_modify(ary);
-    for (i = argc - 1; i >= 0; i--)
+    for (i = argc - 1; i >= 0; i--) {
 	CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
 	    0, (const void *)RB2OC(argv[i]));
+    }
 
     return ary;
 }
@@ -3033,8 +3037,6 @@
     return Qnil;
 }
 
-#define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
-
 /*
  * Recursively compute permutations of r elements of the set [0..n-1].
  * When we have a complete permutation of array indexes, copy the values
@@ -3124,10 +3126,8 @@
 	}
     }
     else {             /* this is the general case */
-	volatile VALUE t0 = tmpbuf(n,sizeof(long));
-	long *p = (long*)RSTRING_BYTEPTR(t0);
-	volatile VALUE t1 = tmpbuf(n,sizeof(int));
-	int *used = (int*)RSTRING_BYTEPTR(t1);
+	long *p = (long *)alloca(n * sizeof(long));
+	int *used = (int *)alloca(n * sizeof(int));
 	VALUE ary0 = rb_ary_dup(ary);
 
 	for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
@@ -3202,8 +3202,7 @@
 	}
     }
     else {
-	volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
-	long *stack = (long*)RSTRING_BYTEPTR(t0);
+	long *stack = (long *)alloca((n + 1) * sizeof(long));
 	long nlen = combi_len(len, n);
 	volatile VALUE cc = rb_ary_new2(n);
 	long lev = 0;
@@ -3246,10 +3245,8 @@
 rb_ary_product(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     int n = argc+1;    /* How many arrays we're operating on */
-    volatile VALUE t0 = tmpbuf(n, sizeof(VALUE));
-    volatile VALUE t1 = tmpbuf(n, sizeof(int));
-    VALUE *arrays = (VALUE*)RSTRING_BYTEPTR(t0); /* The arrays we're computing the product of */
-    int *counters = (int*)RSTRING_BYTEPTR(t1); /* The current position in each one */
+    VALUE *arrays = (VALUE *)alloca(n * sizeof(VALUE));; /* The arrays we're computing the product of */
+    int *counters = (int *)alloca(n * sizeof(int)); /* The current position in each one */
     VALUE result;      /* The array we'll be returning */
     long i,j;
     long resultlen = 1;

Modified: MacRuby/branches/experimental/bignum.c
===================================================================
--- MacRuby/branches/experimental/bignum.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/bignum.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -939,7 +939,7 @@
 rb_big2str0(VALUE x, int base, int trim)
 {
     int off;
-    VALUE ss, xx;
+    VALUE xx;
     long n1, n2, len, hbase;
     char* ptr;
 
@@ -955,8 +955,7 @@
 
     n2 = big2str_find_n1(x, base);
     n1 = (n2 + 1) / 2;
-    ss = rb_usascii_str_new(0, n2 + 1); /* plus one for sign */
-    ptr = RSTRING_BYTEPTR(ss); /* ok */
+    ptr = (char *)alloca(n2 + 1); /* plus one for sign */
     ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-';
 
     hbase = base*base;
@@ -975,10 +974,8 @@
     }
 
     ptr[len] = '\0';
-    rb_str_resize(ss, len);
-    RSTRING_SYNC(ss);
 
-    return ss;
+    return rb_str_new2(ptr);
 }
 
 VALUE

Modified: MacRuby/branches/experimental/dir.c
===================================================================
--- MacRuby/branches/experimental/dir.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/dir.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -464,10 +464,10 @@
     if (dirp->path) {
 	const char *c = rb_obj_classname(dir);
 	int len = strlen(c) + strlen(dirp->path) + 4;
-	VALUE s = rb_str_new(0, len);
-	snprintf(RSTRING_BYTEPTR(s), len+1, "#<%s:%s>", c, dirp->path);
-	RSTRING_SYNC(s);
-	return s;
+	
+	char *buf = (char *)alloca(len);
+	snprintf(buf, len,  "#<%s:%s>", c, dirp->path);
+	return rb_str_new2(buf);
     }
     return rb_funcall(dir, rb_intern("to_s"), 0, 0);
 }

Modified: MacRuby/branches/experimental/encoding.c
===================================================================
--- MacRuby/branches/experimental/encoding.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/encoding.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -288,8 +288,9 @@
 enc_find(VALUE klass, SEL sel, VALUE enc)
 {
     VALUE e = enc_find2(enc);
-    if (e == Qnil)
-	rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
+    if (e == Qnil) {
+	rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_PTR(enc));
+    }
     return e;
 }
 

Modified: MacRuby/branches/experimental/file.c
===================================================================
--- MacRuby/branches/experimental/file.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/file.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -96,9 +96,13 @@
     VALUE tmp;
     static ID to_path;
 
-    if (check) rb_check_safe_obj(obj);
+    if (check) {
+	rb_check_safe_obj(obj);
+    }
     tmp = rb_check_string_type(obj);
-    if (!NIL_P(tmp)) goto exit;
+    if (!NIL_P(tmp)) {
+	goto exit;
+    }
 
     if (!to_path) {
 	to_path = rb_intern("to_path");
@@ -918,35 +922,40 @@
     struct stat st;
     rb_uid_t euid;
 
-    if (stat(path, &st) < 0) return -1;
+    if (stat(path, &st) < 0) {
+	return -1;
+    }
 
     euid = geteuid();
 
     if (euid == 0) {
 	/* Root can read or write any file. */
-	if (!(mode & X_OK))
+	if (!(mode & X_OK)) {
 	    return 0;
+	}
 
 	/* Root can execute any file that has any one of the execute
 	   bits set. */
-	if (st.st_mode & S_IXUGO)
+	if (st.st_mode & S_IXUGO) {
 	    return 0;
+	}
 
 	return -1;
     }
 
-    if (st.st_uid == euid)        /* owner */
+    if (st.st_uid == euid) {       /* owner */
 	mode <<= 6;
-    else if (group_member(st.st_gid))
+    }
+    else if (group_member(st.st_gid)) {
 	mode <<= 3;
+    }
 
-    if ((st.st_mode & mode) == mode) return 0;
+    if ((st.st_mode & mode) == mode) {
+	return 0;
+    }
 
     return -1;
 #else
-# if defined(_MSC_VER) || defined(__MINGW32__)
-    mode &= ~1;
-# endif
     return access(path, mode);
 #endif
 }
@@ -1533,47 +1542,12 @@
 static VALUE
 rb_file_identical_p(VALUE obj, SEL sel, VALUE fname1, VALUE fname2)
 {
-#ifndef DOSISH
     struct stat st1, st2;
 
     if (rb_stat(fname1, &st1) < 0) return Qfalse;
     if (rb_stat(fname2, &st2) < 0) return Qfalse;
     if (st1.st_dev != st2.st_dev) return Qfalse;
     if (st1.st_ino != st2.st_ino) return Qfalse;
-#else
-#ifdef _WIN32
-    BY_HANDLE_FILE_INFORMATION st1, st2;
-    HANDLE f1 = 0, f2 = 0;
-#endif
-
-    rb_secure(2);
-#ifdef _WIN32
-    f1 = w32_io_info(&fname1, &st1);
-    if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
-    f2 = w32_io_info(&fname2, &st2);
-    if (f1) CloseHandle(f1);
-    if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
-    if (f2) CloseHandle(f2);
-
-    if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
-	st1.nFileIndexHigh == st2.nFileIndexHigh &&
-	st1.nFileIndexLow == st2.nFileIndexLow)
-	return Qtrue;
-    if (!f1 || !f2) return Qfalse;
-    if (rb_w32_iswin95()) return Qfalse;
-#else
-    FilePathValue(fname1);
-    fname1 = rb_str_new4(fname1);
-    FilePathValue(fname2);
-    if (access(RSTRING_PTR(fname1), 0)) return Qfalse;
-    if (access(RSTRING_PTR(fname2), 0)) return Qfalse;
-#endif
-    fname1 = rb_file_expand_path(fname1, Qnil);
-    fname2 = rb_file_expand_path(fname2, Qnil);
-    if (RSTRING_LEN(fname1) != RSTRING_LEN(fname2)) return Qfalse;
-    if (rb_memcicmp(RSTRING_PTR(fname1), RSTRING_PTR(fname2), RSTRING_LEN(fname1)))
-	return Qfalse;
-#endif
     return Qtrue;
 }
 
@@ -2337,22 +2311,7 @@
     FilePathValue(to);
     src = StringValueCStr(from);
     dst = StringValueCStr(to);
-#if defined __CYGWIN__
-    errno = 0;
-#endif
     if (rename(src, dst) < 0) {
-#if defined DOSISH && !defined _WIN32
-	switch (errno) {
-	  case EEXIST:
-#if defined (__EMX__)
-	  case EACCES:
-#endif
-	    if (chmod(dst, 0666) == 0 &&
-		unlink(dst) == 0 &&
-		rename(src, dst) == 0)
-		return INT2FIX(0);
-	}
-#endif
 	sys_fail2(from, to);
     }
 
@@ -2393,89 +2352,23 @@
     return INT2FIX(omask);
 }
 
-#ifdef __CYGWIN__
-#undef DOSISH
-#endif
-#if defined __CYGWIN__ || defined DOSISH
-#define DOSISH_UNC
-#define DOSISH_DRIVE_LETTER
-#define isdirsep(x) ((x) == '/' || (x) == '\\')
-#else
 #define isdirsep(x) ((x) == '/')
-#endif
 
-#if defined _WIN32 || defined __CYGWIN__
-#define USE_NTFS 1
-#else
-#define USE_NTFS 0
-#endif
-
-#if USE_NTFS
-#define istrailinggabage(x) ((x) == '.' || (x) == ' ')
-#else
 #define istrailinggabage(x) 0
-#endif
 
-#ifndef CharNext		/* defined as CharNext[AW] on Windows. */
-# if defined(DJGPP)
-#   define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-# else
-#   define CharNext(p) ((p) + 1)
-# endif
+#ifndef CharNext
+# define CharNext(p) ((p) + 1)
 #endif
 
-#ifdef DOSISH_DRIVE_LETTER
-static inline int
-has_drive_letter(const char *buf)
-{
-    if (ISALPHA(buf[0]) && buf[1] == ':') {
-	return 1;
-    }
-    else {
-	return 0;
-    }
-}
-
-static char*
-getcwdofdrv(int drv)
-{
-    char drive[4];
-    char *drvcwd, *oldcwd;
-
-    drive[0] = drv;
-    drive[1] = ':';
-    drive[2] = '\0';
-
-    /* the only way that I know to get the current directory
-       of a particular drive is to change chdir() to that drive,
-       so save the old cwd before chdir()
-    */
-    oldcwd = my_getcwd();
-    if (chdir(drive) == 0) {
-	drvcwd = my_getcwd();
-	chdir(oldcwd);
-	free(oldcwd);
-    }
-    else {
-	/* perhaps the drive is not exist. we return only drive letter */
-	drvcwd = strdup(drive);
-    }
-    return drvcwd;
-}
-#endif
-
 static inline char *
 skiproot(const char *path)
 {
-#ifdef DOSISH_DRIVE_LETTER
-    if (has_drive_letter(path)) path += 2;
-#endif
     while (isdirsep(*path)) path++;
     return (char *)path;
 }
 
 #define nextdirsep rb_path_next
-char *
+static char *
 rb_path_next(const char *s)
 {
     while (*s && !isdirsep(*s)) {
@@ -2484,34 +2377,10 @@
     return (char *)s;
 }
 
-#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 
-#define skipprefix rb_path_skip_prefix
-#else
 #define skipprefix(path) (path)
-#endif
-char *
-rb_path_skip_prefix(const char *path)
-{
-#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) 
-#ifdef DOSISH_UNC
-    if (isdirsep(path[0]) && isdirsep(path[1])) {
-	path += 2;
-	while (isdirsep(*path)) path++;
-	if (*(path = nextdirsep(path)) && path[1] && !isdirsep(path[1]))
-	    path = nextdirsep(path + 1);
-	return (char *)path;
-    }
-#endif
-#ifdef DOSISH_DRIVE_LETTER
-    if (has_drive_letter(path))
-	return (char *)(path + 2);
-#endif
-#endif
-    return (char *)path;
-}
 
 #define strrdirsep rb_path_last_separator
-char *
+static char *
 rb_path_last_separator(const char *path)
 {
     char *last = NULL;
@@ -2552,54 +2421,23 @@
     return chompdirsep(path);
 }
 
-#if USE_NTFS
-static char *
-ntfs_tail(const char *path)
-{
-    while (*path == '.') path++;
-    while (*path && *path != ':') {
-	if (istrailinggabage(*path)) {
-	    const char *last = path++;
-	    while (istrailinggabage(*path)) path++;
-	    if (!*path || *path == ':') return (char *)last;
-	}
-	else if (isdirsep(*path)) {
-	    const char *last = path++;
-	    while (isdirsep(*path)) path++;
-	    if (!*path) return (char *)last;
-	    if (*path == ':') path++;
-	}
-	else {
-	    path = CharNext(path);
-	}
-    }
-    return (char *)path;
-}
-#endif
-
 #define BUFCHECK(cond) do {\
     long bdiff = p - buf;\
     if (cond) {\
 	do {buflen *= 2;} while (cond);\
-	rb_str_resize(result, buflen);\
-	buf = RSTRING_BYTEPTR(result);\
+	rb_bytestring_resize(result, buflen);\
+	buf = (char *)rb_bytestring_byte_pointer(result);\
 	p = buf + bdiff;\
 	pend = buf + buflen;\
     }\
 } while (0)
 
 #define BUFINIT() (\
-    p = buf = RSTRING_BYTEPTR(result),\
-    buflen = RSTRING_BYTELEN(result),\
+    p = buf = (char *)rb_bytestring_byte_pointer(result),\
+    buflen = rb_bytestring_length(result),\
     pend = p + buflen)
 
-#if WITH_OBJC
-# define SET_EXTERNAL_ENCODING()
-#else
-# define SET_EXTERNAL_ENCODING() (\
-    (void)(extenc || (extenc = rb_default_external_encoding())),\
-    rb_enc_associate(result, extenc))
-#endif
+#define SET_EXTERNAL_ENCODING()
 
 static int is_absolute_path(const char*);
 
@@ -2610,9 +2448,6 @@
     char *buf, *p, *pend, *root;
     long buflen, dirlen;
     int tainted;
-#if !WITH_OBJC
-    rb_encoding *extenc = 0;
-#endif
 
     FilePathValue(fname);
     s = StringValuePtr(fname);
@@ -2629,15 +2464,7 @@
 	    dirlen = strlen(dir);
 	    BUFCHECK(dirlen > buflen);
 	    strcpy(buf, dir);
-#if defined DOSISH || defined __CYGWIN__
-	    for (p = buf; *p; p = CharNext(p)) {
-		if (*p == '\\') {
-		    *p = '/';
-		}
-	    }
-#else
 	    p = buf + strlen(dir);
-#endif
 	    s++;
 	    tainted = 1;
 	    SET_EXTERNAL_ENCODING();
@@ -2666,52 +2493,13 @@
 #endif
 	}
     }
-#ifdef DOSISH_DRIVE_LETTER
-    /* skip drive letter */
-    else if (has_drive_letter(s)) {
-	if (isdirsep(s[2])) {
-	    /* specified drive letter, and full path */
-	    /* skip drive letter */
-	    BUFCHECK(bdiff + 2 >= buflen);
-	    memcpy(p, s, 2);
-	    p += 2;
-	    s += 2;
-	}
-	else {
-	    /* specified drive, but not full path */
-	    int same = 0;
-	    if (!NIL_P(dname)) {
-		file_expand_path(dname, Qnil, result);
-		BUFINIT();
-		if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
-		    /* ok, same drive */
-		    same = 1;
-		}
-	    }
-	    if (!same) {
-		char *dir = getcwdofdrv(*s);
-
-		tainted = 1;
-		dirlen = strlen(dir);
-		BUFCHECK(dirlen > buflen);
-		strcpy(buf, dir);
-		free(dir);
-		SET_EXTERNAL_ENCODING();
-	    }
-	    p = chompdirsep(skiproot(buf));
-	    s += 2;
-	}
-    }
-#endif
     else if (!is_absolute_path(s)) {
 	if (!NIL_P(dname)) {
 	    long n;
 	    file_expand_path(dname, Qnil, result);
 	    BUFINIT();
-#if WITH_OBJC
 	    n = RSTRING_LEN(result);
 	    BUFCHECK(n + 2 > buflen);
-#endif
 	}
 	else {
 	    char *dir = my_getcwd();
@@ -2723,15 +2511,7 @@
 	    xfree(dir);
 	    SET_EXTERNAL_ENCODING();
 	}
-#if defined DOSISH || defined __CYGWIN__
-	if (isdirsep(*s)) {
-	    /* specified full path, but not drive letter nor UNC */
-	    /* we need to get the drive letter or UNC share name */
-	    p = skipprefix(buf);
-	}
-	else
-#endif
-	    p = chompdirsep(skiproot(buf));
+	p = chompdirsep(skiproot(buf));
     }
     else {
 	b = s;
@@ -2773,16 +2553,8 @@
 			}
 			b = ++s;
 		    }
-#if USE_NTFS
-		    else {
-			do *++s; while (istrailinggabage(*s));
-		    }
-#endif
 		    break;
 		  case '/':
-#if defined DOSISH || defined __CYGWIN__
-		  case '\\':
-#endif
 		    b = ++s;
 		    break;
 		  default:
@@ -2790,24 +2562,8 @@
 		    break;
 		}
 	    }
-#if USE_NTFS
-	    else {
-		--s;
-	      case ' ': {
-		const char *e = s;
-		while (istrailinggabage(*s)) s++;
-		if (!*s) {
-		    s = e;
-		    goto endpath;
-		}
-	      }
-	    }
-#endif
 	    break;
 	  case '/':
-#if defined DOSISH || defined __CYGWIN__
-	  case '\\':
-#endif
 	    if (s > b) {
 		long rootdiff = root - buf;
 		BUFCHECK(bdiff + (s-b+1) >= buflen);
@@ -2825,90 +2581,25 @@
     }
 
     if (s > b) {
-#if USE_NTFS
-      endpath:
-	if (s > b + 6 && strncasecmp(s - 6, ":$DATA", 6) == 0) {
-	    /* alias of stream */
-	    /* get rid of a bug of x64 VC++ */
-	    if (*(s-7) == ':') s -= 7;			/* prime */
-	    else if (memchr(b, ':', s - 6 - b)) s -= 6; /* alternative */
-	}
-#endif
 	BUFCHECK(bdiff + (s-b) >= buflen);
 	memcpy(++p, b, s-b);
 	p += s-b;
     }
     if (p == skiproot(buf) - 1) p++;
 
-#if USE_NTFS
-    *p = '\0';
-    if (1 &&
-#ifdef __CYGWIN__
-	!(buf[0] == '/' && !buf[1]) &&
-#endif
-	!strpbrk(b = buf, "*?")) {
-	size_t len;
-	WIN32_FIND_DATA wfd;
-#ifdef __CYGWIN__
-	int lnk_added = 0, is_symlink = 0;
-	struct stat st;
-	char w32buf[MAXPATHLEN], sep = 0;
-	p = 0;
-	if (lstat(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
-	    is_symlink = 1;
-	    p = strrdirsep(buf);
-	    if (!p) p = skipprefix(buf);
-	    if (p) {
-		sep = *p;
-		*p = '\0';
-	    }
-	}
-	if (cygwin_conv_to_win32_path(buf, w32buf) == 0) {
-	    b = w32buf;
-	}
-	if (p) *p = sep;
-	else p = buf;
-	if (is_symlink && b == w32buf) {
-	    len = strlen(p);
-	    if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) {
-		lnk_added = 1;
-		strlcat(w32buf, ".lnk", sizeof(w32buf));
-	    }
-	}
-#endif
-	HANDLE h = FindFirstFile(b, &wfd);
-	if (h != INVALID_HANDLE_VALUE) {
-	    FindClose(h);
-	    p = strrdirsep(buf);
-	    len = strlen(wfd.cFileName);
-#ifdef __CYGWIN__
-	    if (lnk_added && len > 4 &&
-		STRCASECMP(wfd.cFileName + len - 4, ".lnk") == 0) {
-		wfd.cFileName[len -= 4] = '\0';
-	    }
-#endif
-	    if (!p) p = buf;
-	    else ++p;
-	    BUFCHECK(bdiff + len >= buflen);
-	    memcpy(p, wfd.cFileName, len + 1);
-	    p += len;
-	}
+    if (tainted) {
+	OBJ_TAINT(result);
     }
-#endif
-
-    if (tainted) OBJ_TAINT(result);
-    rb_str_set_len(result, p - buf);
-#if !WITH_OBJC
-    rb_enc_check(fname, result);
-#endif
-    RSTRING_SYNC(result);
+    rb_bytestring_resize(result, p - buf);
     return result;
 }
 
 VALUE
 rb_file_expand_path(VALUE fname, VALUE dname)
 {
-    return file_expand_path(fname, dname, rb_usascii_str_new(0, MAXPATHLEN + 2));
+    VALUE bstr = rb_bytestring_new();
+    rb_bytestring_resize(bstr, MAXPATHLEN + 2);
+    return file_expand_path(fname, dname, bstr);
 }
 
 /*
@@ -2989,42 +2680,21 @@
 {
     VALUE fname, fext, basename;
     const char *name, *p;
-#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
-    char *root;
-#endif
     int f, n;
 
     if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
 	StringValue(fext);
     }
     FilePathStringValue(fname);
-    if (RSTRING_LEN(fname) == 0 || !*(name = RSTRING_PTR(fname)))
+    if (RSTRING_LEN(fname) == 0 || !*(name = RSTRING_PTR(fname))) {
 	return fname;
+    }
     name = skipprefix(name);
-#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
-    root = name;
-#endif
     while (isdirsep(*name))
 	name++;
     if (!*name) {
 	p = name - 1;
 	f = 1;
-#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
-	if (name != root) {
-	    /* has slashes */
-	}
-#ifdef DOSISH_DRIVE_LETTER
-	else if (*p == ':') {
-	    p++;
-	    f = 0;
-	}
-#endif
-#ifdef DOSISH_UNC
-	else {
-	    p = "/";
-	}
-#endif
-#endif
     }
     else {
 	if (!(p = strrdirsep(name))) {
@@ -3033,20 +2703,13 @@
 	else {
 	    while (isdirsep(*p)) p++; /* skip last / */
 	}
-#if USE_NTFS
-	n = ntfs_tail(p) - p;
-#else
 	n = chompdirsep(p) - p;
-#endif
 	if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
 	    f = n;
 	}
 	if (f == RSTRING_LEN(fname)) return fname;
     }
     basename = rb_str_new(p, f);
-#if !WITH_OBJC
-    rb_enc_copy(basename, fname);
-#endif
     OBJ_INFECT(basename, fname);
     return basename;
 }
@@ -3072,35 +2735,16 @@
     FilePathStringValue(fname);
     name = StringValueCStr(fname);
     root = skiproot(name);
-#ifdef DOSISH_UNC
-    if (root > name + 1 && isdirsep(*name))
-	root = skipprefix(name = root - 2);
-#else
-    if (root > name + 1)
+    if (root > name + 1) {
 	name = root - 1;
-#endif
+    }
     p = strrdirsep(root);
     if (!p) {
 	p = root;
     }
     if (p == name)
 	return rb_usascii_str_new2(".");
-#ifdef DOSISH_DRIVE_LETTER
-    if (has_drive_letter(name) && isdirsep(*(name + 2))) {
-	const char *top = skiproot(name + 2);
-	dirname = rb_str_new(name, 3);
-	rb_str_cat(dirname, top, p - top);
-    }
-    else
-#endif
     dirname = rb_str_new(name, p - name);
-#ifdef DOSISH_DRIVE_LETTER
-    if (has_drive_letter(name) && root == name + 2 && p - name == 2)
-	rb_str_cat(dirname, ".", 1);
-#endif
-#if !WITH_OBJC
-    rb_enc_copy(dirname, fname);
-#endif
     OBJ_INFECT(dirname, fname);
     return dirname;
 }
@@ -3136,27 +2780,8 @@
     e = 0;
     while (*p) {
 	if (*p == '.' || istrailinggabage(*p)) {
-#if USE_NTFS
-	    const char *last = p++, *dot = last;
-	    while (istrailinggabage(*p)) {
-		if (*p == '.') dot = p;
-		p++;
-	    }
-	    if (!*p || *p == ':') {
-		p = last;
-		break;
-	    }
-	    e = dot;
-	    continue;
-#else
 	    e = p;	  /* get the last dot of the last component */
-#endif
 	}
-#if USE_NTFS
-	else if (*p == ':') {
-	    break;
-	}
-#endif
 	else if (isdirsep(*p))
 	    break;
 	p = CharNext(p);
@@ -3164,9 +2789,6 @@
     if (!e || e == name || e+1 == p)	/* no dot, or the only dot is first or end? */
 	return rb_str_new(0, 0);
     extname = rb_str_new(e, p - e);	/* keep the dot, too! */
-#if !WITH_OBJC
-    rb_enc_copy(extname, fname);
-#endif
     OBJ_INFECT(extname, fname);
     return extname;
 }
@@ -3210,24 +2832,12 @@
 
 static VALUE rb_file_join(VALUE ary, VALUE sep);
 
-#if !WITH_OBJC
 static VALUE
-file_inspect_join(VALUE ary, VALUE argp, int recur)
-{
-    VALUE *arg = (VALUE *)argp;
-    if (recur) return rb_usascii_str_new2("[...]");
-    return rb_file_join(arg[0], arg[1]);
-}
-#endif
-
-static VALUE
 rb_file_join(VALUE ary, VALUE sep)
 {
-#if WITH_OBJC
-    CFMutableStringRef mstr;
     long count;
 
-    mstr = CFStringCreateMutable(NULL, 0);
+    CFMutableStringRef mstr = CFStringCreateMutable(NULL, 0);
 
     count = RARRAY_LEN(ary);
     if (count > 0) {
@@ -3249,61 +2859,8 @@
 	}
     }
     CFMakeCollectable(mstr);
-    return (VALUE)mstr;
-#else
-    long len, i, count;
-    VALUE result, tmp;
-    char *name, *tail;
 
-    if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0);
-
-    len = 1;
-    for (i=0, count=RARRAY_LEN(ary); i<count; i++) {
-	if (TYPE(RARRAY_AT(ary, i)) == T_STRING) {
-	    len += RSTRING_BYTELEN(RARRAY_AT(ary, i));
-	}
-	else {
-	    len += 10;
-	}
-    }
-    if (!NIL_P(sep)) {
-	StringValue(sep);
-	len += RSTRING_BYTELEN(sep) * RARRAY_LEN(ary) - 1;
-    }
-    result = rb_str_buf_new(len);
-    OBJ_INFECT(result, ary);
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	tmp = RARRAY_AT(ary, i);
-	switch (TYPE(tmp)) {
-	  case T_STRING:
-	    break;
-	  case T_ARRAY:
-	    {
-		VALUE args[2];
-
-		args[0] = tmp;
-		args[1] = sep;
-		tmp = rb_exec_recursive(file_inspect_join, ary, (VALUE)args);
-	    }
-	    break;
-	  default:
-	    FilePathStringValue(tmp);
-	}
-	name = StringValueCStr(result);
-	if (i > 0 && !NIL_P(sep)) {
-	    tail = chompdirsep(name);
-	    if (RSTRING_BYTEPTR(tmp) && isdirsep(RSTRING_BYTEPTR(tmp)[0])) {
-		rb_str_set_len(result, tail - name);
-	    }
-	    else if (!*tail) {
-		rb_str_buf_append(result, sep);
-	    }
-	}
-	rb_str_buf_append(result, tmp);
-    }
-
-    return result;
-#endif
+    return (VALUE)mstr;
 }
 
 /*
@@ -4382,24 +3939,11 @@
 static int
 is_absolute_path(const char *path)
 {
-#ifdef DOSISH_DRIVE_LETTER
-    if (has_drive_letter(path) && isdirsep(path[2])) return 1;
-#endif
-#ifdef DOSISH_UNC
-    if (isdirsep(path[0]) && isdirsep(path[1])) return 1;
-#endif
-#ifndef DOSISH
-    if (path[0] == '/') return 1;
-#endif
-    return 0;
+    return path[0] == '/';
 }
 
 #ifndef ENABLE_PATH_CHECK
-# if defined DOSISH || defined __CYGWIN__
-#   define ENABLE_PATH_CHECK 0
-# else
-#   define ENABLE_PATH_CHECK 1
-# endif
+#  define ENABLE_PATH_CHECK 1
 #endif
 
 #if ENABLE_PATH_CHECK
@@ -4482,16 +4026,7 @@
     return 1;
 }
 
-#if defined(__MACOS__) || defined(riscos)
 static int
-is_macos_native_path(const char *path)
-{
-    if (strchr(path, ':')) return 1;
-    return 0;
-}
-#endif
-
-static int
 file_load_ok(const char *path)
 {
     return eaccess(path, R_OK) == 0;
@@ -4572,15 +4107,6 @@
 	f = StringValueCStr(path);
     }
 
-#if defined(__MACOS__) || defined(riscos)
-    if (is_macos_native_path(f)) {
-	if (rb_safe_level() >= 1 && !fpath_check(f)) {
-	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
-	}
-	if (file_load_ok(f)) return path;
-    }
-#endif
-
     if (is_absolute_path(f)) {
 	if (rb_safe_level() >= 1 && !fpath_check(f)) {
 	    rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
@@ -4746,11 +4272,7 @@
     rb_objc_define_method(rb_ccFile, "split",  rb_file_s_split, 1);
     rb_objc_define_method(rb_ccFile, "join",   rb_file_s_join, -2);
 
-#ifdef DOSISH
-    rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_usascii_str_new2("\\")));
-#else
     rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
-#endif
     rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_obj_freeze(rb_str_new2(PATH_SEP)));
 
     rb_objc_define_method(rb_cIO, "stat",  rb_io_stat, 0); /* this is IO's method */

Modified: MacRuby/branches/experimental/hash.c
===================================================================
--- MacRuby/branches/experimental/hash.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/hash.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -1144,7 +1144,9 @@
 {
     VALUE str2;
 
-    if (key == Qundef) return ST_CONTINUE;
+    if (key == Qundef) {
+	return ST_CONTINUE;
+    }
     if (RSTRING_LEN(str) > 1) {
 	rb_str_cat2(str, ", ");
     }
@@ -1162,7 +1164,9 @@
 {
     VALUE str;
 
-    if (recur) return rb_usascii_str_new2("{...}");
+    if (recur) {
+	return rb_usascii_str_new2("{...}");
+    }
     str = rb_str_buf_new2("{");
     rb_hash_foreach(hash, inspect_i, str);
     rb_str_buf_cat2(str, "}");

Modified: MacRuby/branches/experimental/id.c
===================================================================
--- MacRuby/branches/experimental/id.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/id.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -65,6 +65,7 @@
     selRespondTo = sel_registerName("respond_to?:");
     selMethodMissing = sel_registerName("method_missing:");
     selCopy = sel_registerName("copy");
+    selMutableCopy = sel_registerName("mutableCopy");
     sel_ignored = sel_registerName("retain");
     assert(sel_ignored == sel_registerName("release"));
     sel_zone = sel_registerName("zone");

Modified: MacRuby/branches/experimental/id.h
===================================================================
--- MacRuby/branches/experimental/id.h	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/id.h	2009-03-16 02:26:09 UTC (rev 929)
@@ -77,6 +77,7 @@
 extern SEL selRespondTo;
 extern SEL selMethodMissing;
 extern SEL selCopy;
+extern SEL selMutableCopy;
 extern SEL selToS;
 extern SEL sel_ignored;
 extern SEL sel_zone;

Modified: MacRuby/branches/experimental/include/ruby/intern.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/intern.h	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/include/ruby/intern.h	2009-03-16 02:26:09 UTC (rev 929)
@@ -322,9 +322,7 @@
 void rb_file_const(const char*, VALUE);
 int rb_find_file_ext(VALUE*, const char* const*);
 VALUE rb_find_file(VALUE);
-char *rb_path_next(const char *);
-char *rb_path_skip_prefix(const char *);
-char *rb_path_last_separator(const char *);
+#define rb_path_skip_prefix(path) (path)
 char *rb_path_end(const char *);
 VALUE rb_file_directory_p(VALUE,SEL,VALUE);
 /* gc.c */

Modified: MacRuby/branches/experimental/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/ruby.h	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/include/ruby/ruby.h	2009-03-16 02:26:09 UTC (rev 929)
@@ -360,6 +360,8 @@
 CFMutableDataRef rb_bytestring_wrapped_data(VALUE);
 UInt8 *rb_bytestring_byte_pointer(VALUE);
 VALUE rb_coerce_to_bytestring(VALUE);
+long rb_bytestring_length(VALUE str);
+void rb_bytestring_resize(VALUE str, long newsize);
 
 void rb_check_safe_obj(VALUE);
 void rb_check_safe_str(VALUE);
@@ -581,21 +583,8 @@
      RSTRING(str)->as.ary : \
      RSTRING(str)->as.heap.ptr)
 #else
-/* IMPORTANT: try to avoid using RSTRING_PTR/RSTRING_LEN if necessary, 
- * because they can be slow operations in non-8bit strings. 
- * If you modify RSTRING_BYTEPTR, you need to call RSTRING_SYNC in order to
- * synchronize its content with the real string storage.
- * RSTRING_BYTEPTR/RSTRING_BYTELEN deal with bytes. If you want to access a C string
- * pointer, please use RSTRING_PTR/RSTRING/LEN instead which are faster.
- */
-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_BYTEPTR(str) (rb_str_byteptr((VALUE)str))
-# define RSTRING_BYTELEN(str) (rb_str_bytelen((VALUE)str))
-# define RSTRING_SYNC(str) (rb_str_bytesync((VALUE)str))
 # define RSTRING_PTR(str) (rb_str_cstr((VALUE)str))
 # define RSTRING_LEN(str) (rb_str_clen((VALUE)str))
 #endif
@@ -814,7 +803,7 @@
 
 #define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
 
-#define FL_ABLE(x) (!SPECIAL_CONST_P(x) && BUILTIN_TYPE(x) != T_NODE)
+#define FL_ABLE(x) (!SPECIAL_CONST_P(x) && !NATIVE(x) && BUILTIN_TYPE(x) != T_NODE)
 #define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
 #define FL_ANY(x,f) FL_TEST(x,f)
 #define FL_ALL(x,f) (FL_TEST(x,f) == (f))

Modified: MacRuby/branches/experimental/io.c
===================================================================
--- MacRuby/branches/experimental/io.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/io.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -409,14 +409,22 @@
 	length = CFDataGetLength(data);
     }
     else {
-	buffer = (UInt8 *)CFStringGetCStringPtr((CFStringRef)to_write,
-		kCFStringEncodingUTF8);
+	buffer = (UInt8 *)RSTRING_PTR(to_write);
 	if (buffer != NULL) {
-	    length = CFStringGetLength((CFStringRef)to_write);
+	    length = RSTRING_LEN(to_write);
 	}
 	else {
-	    buffer = (UInt8 *)rb_str_byteptr(to_write);
-	    length = (CFIndex)rb_str_bytelen(to_write);
+	    const long max = CFStringGetMaximumSizeForEncoding(
+		    CFStringGetLength((CFStringRef)to_write),
+		    kCFStringEncodingUTF8);
+
+	    buffer = (UInt8 *)alloca(max + 1);
+	    if (!CFStringGetCString((CFStringRef)to_write, (char *)buffer, 
+			max, kCFStringEncodingUTF8)) {
+		// XXX what could we do?
+		abort();
+	    }
+	    length = strlen((char *)buffer);
 	}
     }
 
@@ -2211,18 +2219,19 @@
  */
 
 static VALUE
-rb_f_p(VALUE self, SEL sel, int argc, VALUE *argv) {
+rb_f_p(VALUE self, SEL sel, int argc, VALUE *argv)
+{
     int i;
     VALUE ret = Qnil;
 
-    for (i=0; i<argc; i++) {
-	    rb_p(argv[i], (SEL)0);
+    for (i = 0; i < argc; i++) {
+	rb_p(argv[i], 0);
     }
     if (argc == 1) {
-	    ret = argv[0];
+	ret = argv[0];
     }
     else if (argc > 1) {
-	    ret = rb_ary_new4(argc, argv);
+	ret = rb_ary_new4(argc, argv);
     }
 
     return ret;
@@ -3401,7 +3410,7 @@
 	if (ruby_inplace_mode != NULL) {
 	    free(ruby_inplace_mode);
 	}
-	ruby_inplace_mode = strdup(RSTRING_BYTEPTR(val));
+	ruby_inplace_mode = strdup(RSTRING_PTR(val));
     }
     return argf;
 }

Modified: MacRuby/branches/experimental/marshal.c
===================================================================
--- MacRuby/branches/experimental/marshal.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/marshal.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -945,7 +945,8 @@
 	GC_WB(&arg->str, port);
     }
 
-    RSTRING_BYTEPTR(arg->str); /* force bytestring creation */
+    // TODO should create ByteString
+    //RSTRING_BYTEPTR(arg->str); /* force bytestring creation */
 
     GC_WB(&arg->symbols, st_init_numtable());
     GC_WB(&arg->data, st_init_numtable());

Modified: MacRuby/branches/experimental/numeric.c
===================================================================
--- MacRuby/branches/experimental/numeric.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/numeric.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -19,10 +19,6 @@
 #include <ruby/node.h>
 #include "roxor.h"
 
-#if defined(__FreeBSD__) && __FreeBSD__ < 4
-#include <floatingpoint.h>
-#endif
-
 #ifdef HAVE_FLOAT_H
 #include <float.h>
 #endif
@@ -87,9 +83,7 @@
 static ID id_coerce, id_to_i, id_eq;
 
 VALUE rb_cNumeric;
-#if WITH_OBJC
 VALUE rb_cCFNumber;
-#endif
 VALUE rb_cFloat;
 VALUE rb_cInteger;
 VALUE rb_cFixnum;
@@ -97,7 +91,6 @@
 VALUE rb_eZeroDivError;
 VALUE rb_eFloatDomainError;
 
-#if WITH_OBJC
 static CFMutableDictionaryRef fixnum_dict = NULL;
 static struct RFixnum *fixnum_cache = NULL;
 
@@ -134,7 +127,6 @@
 
     return (VALUE)val;
 }
-#endif
 
 void
 rb_num_zerodiv(void)
@@ -180,7 +172,7 @@
 
     rb_raise(rb_eTypeError, "%s can't be coerced into %s",
 	     rb_special_const_p(x[1])?
-	     RSTRING_BYTEPTR(v):
+	     RSTRING_PTR(v):
 	     rb_obj_classname(x[1]),
 	     rb_obj_classname(x[0]));
     return Qnil;		/* dummy */
@@ -1940,9 +1932,6 @@
 int_chr(VALUE num, SEL sel, int argc, VALUE *argv)
 {
     char c;
-#if !WITH_OBJC
-    int n;
-#endif
     long i = NUM2LONG(num);
     rb_encoding *enc;
     VALUE str;
@@ -1950,9 +1939,6 @@
     switch (argc) {
       case 0:
 	if (i < 0 || 0xff < i) {
-#if !WITH_OBJC
-	  out_of_range:
-#endif
 	    rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i);
 	}
 	c = i;
@@ -1968,16 +1954,8 @@
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
 	break;
     }
-#if WITH_OBJC
     enc = rb_to_encoding(argv[0]);
     str = rb_enc_str_new(&c, 1, enc);
-#else
-    enc = rb_to_encoding(argv[0]);
-    if (!enc) enc = rb_ascii8bit_encoding();
-    if (i < 0 || (n = rb_enc_codelen(i, enc)) <= 0) goto out_of_range;
-    str = rb_enc_str_new(0, n, enc);
-    rb_enc_mbcput(i, RSTRING_BYTEPTR(str), enc);
-#endif
     return str;
 }
 
@@ -3176,7 +3154,6 @@
     return Qtrue;
 }
 
-#if WITH_OBJC
 static const char *
 imp_rb_float_objCType(void *rcv, SEL sel)
 {
@@ -3236,7 +3213,6 @@
     rb_objc_install_method2(klass, "longValue",
 	    (IMP)imp_rb_fixnum_longValue);
 }
-#endif
 
 void
 Init_Numeric(void)
@@ -3247,7 +3223,6 @@
 
     rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
     rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
-#if WITH_OBJC
     rb_cCFNumber = (VALUE)objc_getClass("NSCFNumber");
     rb_cNumeric = rb_define_class("Numeric", (VALUE)objc_getClass("NSNumber"));
     RCLASS_SET_VERSION_FLAG(rb_cNumeric, RCLASS_IS_OBJECT_SUBCLASS);
@@ -3255,9 +3230,6 @@
     /* overriding NSObject methods */
     rb_objc_define_method(rb_cNumeric, "class", rb_obj_class, 0);
     rb_objc_define_method(rb_cNumeric, "dup", rb_obj_dup, 0);
-#else
-    rb_cNumeric = rb_define_class("Numeric", rb_cObject);
-#endif
 
     rb_objc_define_method(rb_cNumeric, "singleton_method_added", num_sadded, 1);
     rb_include_module(rb_cNumeric, rb_mComparable);
@@ -3416,7 +3388,5 @@
     rb_objc_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
     rb_objc_define_method(rb_cFloat, "finite?",   flo_is_finite_p, 0);
 
-#if WITH_OBJC
     rb_install_nsnumber_primitives();
-#endif
 }

Modified: MacRuby/branches/experimental/object.c
===================================================================
--- MacRuby/branches/experimental/object.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/object.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -771,6 +771,11 @@
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
 	    case T_STRING:
+		if (*(VALUE *)obj == rb_cByteString) {
+		    // TODO
+		    return Qfalse;
+		}
+		// fall through
 	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
@@ -780,8 +785,9 @@
 		return rb_objc_flag_check((const void *)obj, FL_TAINT) ? Qtrue : Qfalse;
 	}
     }
-    if (FL_TEST(obj, FL_TAINT))
+    if (FL_TEST(obj, FL_TAINT)) {
 	return Qtrue;
+    }
     return Qfalse;
 }
 
@@ -801,6 +807,11 @@
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
 	    case T_STRING:
+		if (*(VALUE *)obj == rb_cByteString) {
+		    // TODO
+		    return obj;
+		}
+		// fall through
 	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
@@ -836,6 +847,11 @@
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
 	    case T_STRING:
+		if (*(VALUE *)obj == rb_cByteString) {
+		    // TODO
+		    return obj;
+		}
+		// fall through
 	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
@@ -901,6 +917,11 @@
 	else if (NATIVE(obj)) {
 	    switch(TYPE(obj)) {
 		case T_STRING:
+		if (*(VALUE *)obj == rb_cByteString) {
+		    // TODO
+		    return obj;
+		}
+		// fall through
 		case T_ARRAY:
 		case T_HASH:
 #ifdef __LP64__
@@ -942,6 +963,11 @@
     }
     switch (TYPE(obj)) {
 	case T_STRING:
+	    if (*(VALUE *)obj == rb_cByteString) {
+		// TODO
+		return Qfalse;
+	    }
+	    // fall through
 	case T_ARRAY:
 	case T_HASH:
 #ifdef __LP64__

Modified: MacRuby/branches/experimental/pack.c
===================================================================
--- MacRuby/branches/experimental/pack.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/pack.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -364,8 +364,8 @@
 #endif
 static const char toofew[] = "too few arguments";
 
-static void encodes(VALUE,const char*,long,int);
-static void qpencode(VALUE,VALUE,long);
+static void encodes(CFMutableDataRef,const char*,long,int);
+static void qpencode(CFMutableDataRef,VALUE,long);
 
 static unsigned long utf8_to_uv(const char*,long*);
 
@@ -440,7 +440,7 @@
     static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
     static const char spc10[] = "          ";
     const char *p, *pend;
-    VALUE res, from, associates = 0;
+    VALUE from, associates = 0;
     char type;
     long items, len, idx, plen;
     const char *ptr;
@@ -451,11 +451,9 @@
     StringValue(fmt);
     p = RSTRING_PTR(fmt);
     pend = p + RSTRING_LEN(fmt);
-    res = rb_str_buf_new(0);
 
-#if WITH_OBJC
-    RSTRING_BYTEPTR(res); /* create bytestring */
-#endif
+    VALUE bres = rb_bytestring_new();
+    CFMutableDataRef data = rb_bytestring_wrapped_data(bres);
 
     items = RARRAY_LEN(ary);
     idx = 0;
@@ -521,9 +519,6 @@
 		StringValue(from);
 		ptr = RSTRING_PTR(from);
 		plen = RSTRING_LEN(from);
-#if !WITH_OBJC
-		OBJ_INFECT(res, from);
-#endif
 	    }
 
 	    if (p[-1] == '*')
@@ -534,18 +529,19 @@
 	      case 'A':         /* arbitrary binary string (ASCII space padded) */
 	      case 'Z':         /* null terminated string  */
 		if (plen >= len) {
-		    rb_str_buf_cat(res, ptr, len);
-		    if (p[-1] == '*' && type == 'Z')
-			rb_str_buf_cat(res, nul10, 1);
+		    CFDataAppendBytes(data, (const UInt8 *)ptr, len);
+		    if (p[-1] == '*' && type == 'Z') {
+			CFDataAppendBytes(data, (const UInt8 *)nul10, 1);
+		    }
 		}
 		else {
-		    rb_str_buf_cat(res, ptr, plen);
+		    CFDataAppendBytes(data, (const UInt8 *)ptr, plen);
 		    len -= plen;
 		    while (len >= 10) {
-			rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
+			CFDataAppendBytes(data, (const UInt8 *)((type == 'A')?spc10:nul10), 10);
 			len -= 10;
 		    }
-		    rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
+		    CFDataAppendBytes(data, (const UInt8 *)((type == 'A')?spc10:nul10), len);
 		}
 		break;
 
@@ -565,7 +561,7 @@
 			    byte >>= 1;
 			else {
 			    char c = byte & 0xff;
-			    rb_str_buf_cat(res, &c, 1);
+			    CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 			    byte = 0;
 			}
 		    }
@@ -573,7 +569,7 @@
 			char c;
 			byte >>= 7 - (len & 7);
 			c = byte & 0xff;
-			rb_str_buf_cat(res, &c, 1);
+			CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 		    }
 		    len = j;
 		    goto grow;
@@ -595,7 +591,7 @@
 			    byte <<= 1;
 			else {
 			    char c = byte & 0xff;
-			    rb_str_buf_cat(res, &c, 1);
+			    CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 			    byte = 0;
 			}
 		    }
@@ -603,7 +599,7 @@
 			char c;
 			byte <<= 7 - (len & 7);
 			c = byte & 0xff;
-			rb_str_buf_cat(res, &c, 1);
+			CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 		    }
 		    len = j;
 		    goto grow;
@@ -628,13 +624,13 @@
 			    byte >>= 4;
 			else {
 			    char c = byte & 0xff;
-			    rb_str_buf_cat(res, &c, 1);
+			    CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 			    byte = 0;
 			}
 		    }
 		    if (len & 1) {
 			char c = byte & 0xff;
-			rb_str_buf_cat(res, &c, 1);
+			CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 		    }
 		    len = j;
 		    goto grow;
@@ -659,13 +655,13 @@
 			    byte <<= 4;
 			else {
 			    char c = byte & 0xff;
-			    rb_str_buf_cat(res, &c, 1);
+			    CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 			    byte = 0;
 			}
 		    }
 		    if (len & 1) {
 			char c = byte & 0xff;
-			rb_str_buf_cat(res, &c, 1);
+			CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 		    }
 		    len = j;
 		    goto grow;
@@ -681,7 +677,7 @@
 
 		from = NEXTFROM;
 		c = num2i32(from);
-		rb_str_buf_cat(res, &c, sizeof(char));
+		CFDataAppendBytes(data, (const UInt8 *)&c, 1);
 	    }
 	    break;
 
@@ -692,7 +688,7 @@
 
 		from = NEXTFROM;
 		s = num2i32(from);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
+		CFDataAppendBytes(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
 	    }
 	    break;
 
@@ -703,7 +699,7 @@
 
 		from = NEXTFROM;
 		i = num2i32(from);
-		rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4));
+		CFDataAppendBytes(data, (const UInt8 *)OFF32(&i), NATINT_LEN(int,4));
 	    }
 	    break;
 
@@ -714,7 +710,7 @@
 
 		from = NEXTFROM;
 		l = num2i32(from);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
+		CFDataAppendBytes(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
 	    }
 	    break;
 
@@ -725,7 +721,7 @@
 
 		from = NEXTFROM;
 		rb_quad_pack(tmp, from);
-		rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE);
+		CFDataAppendBytes(data, (const UInt8 *)&tmp, QUAD_SIZE);
 	    }
 	    break;
 
@@ -736,7 +732,7 @@
 		from = NEXTFROM;
 		s = num2i32(from);
 		s = NATINT_HTONS(s);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
+		CFDataAppendBytes(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
 	    }
 	    break;
 
@@ -747,7 +743,7 @@
 		from = NEXTFROM;
 		l = num2i32(from);
 		l = NATINT_HTONL(l);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
+		CFDataAppendBytes(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
 	    }
 	    break;
 
@@ -758,7 +754,7 @@
 		from = NEXTFROM;
 		s = num2i32(from);
 		s = NATINT_HTOVS(s);
-		rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
+		CFDataAppendBytes(data, (const UInt8 *)OFF16(&s), NATINT_LEN(short,2));
 	    }
 	    break;
 
@@ -769,7 +765,7 @@
 		from = NEXTFROM;
 		l = num2i32(from);
 		l = NATINT_HTOVL(l);
-		rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
+		CFDataAppendBytes(data, (const UInt8 *)OFF32(&l), NATINT_LEN(long,4));
 	    }
 	    break;
 
@@ -780,7 +776,7 @@
 
 		from = NEXTFROM;
 		f = RFLOAT_VALUE(rb_Float(from));
-		rb_str_buf_cat(res, (char*)&f, sizeof(float));
+		CFDataAppendBytes(data, (const UInt8 *)&f, sizeof(float));
 	    }
 	    break;
 
@@ -792,7 +788,7 @@
 		from = NEXTFROM;
 		f = RFLOAT_VALUE(rb_Float(from));
 		f = HTOVF(f,ftmp);
-		rb_str_buf_cat(res, (char*)&f, sizeof(float));
+		CFDataAppendBytes(data, (const UInt8 *)&f, sizeof(float));
 	    }
 	    break;
 
@@ -804,7 +800,7 @@
 		from = NEXTFROM;
 		d = RFLOAT_VALUE(rb_Float(from));
 		d = HTOVD(d,dtmp);
-		rb_str_buf_cat(res, (char*)&d, sizeof(double));
+		CFDataAppendBytes(data, (const UInt8 *)&d, sizeof(double));
 	    }
 	    break;
 
@@ -815,7 +811,7 @@
 
 		from = NEXTFROM;
 		d = RFLOAT_VALUE(rb_Float(from));
-		rb_str_buf_cat(res, (char*)&d, sizeof(double));
+		CFDataAppendBytes(data, (const UInt8 *)&d, sizeof(double));
 	    }
 	    break;
 
@@ -827,7 +823,7 @@
 		from = NEXTFROM;
 		f = RFLOAT_VALUE(rb_Float(from));
 		f = HTONF(f,ftmp);
-		rb_str_buf_cat(res, (char*)&f, sizeof(float));
+		CFDataAppendBytes(data, (const UInt8 *)&f, sizeof(float));
 	    }
 	    break;
 
@@ -839,32 +835,37 @@
 		from = NEXTFROM;
 		d = RFLOAT_VALUE(rb_Float(from));
 		d = HTOND(d,dtmp);
-		rb_str_buf_cat(res, (char*)&d, sizeof(double));
+		CFDataAppendBytes(data, (const UInt8 *)&d, sizeof(double));
 	    }
 	    break;
 
 	  case 'x':		/* null byte */
 	  grow:
 	    while (len >= 10) {
-		rb_str_buf_cat(res, nul10, 10);
+		CFDataAppendBytes(data, (const UInt8 *)nul10, 10);
 		len -= 10;
 	    }
-	    rb_str_buf_cat(res, nul10, len);
+	    CFDataAppendBytes(data, (const UInt8 *)nul10, len);
 	    break;
 
 	  case 'X':		/* back up byte */
 	  shrink:
-	    plen = RSTRING_LEN(res);
-	    if (plen < len)
+	    plen = CFDataGetLength(data);
+	    if (plen < len) {
 		rb_raise(rb_eArgError, "X outside of string");
-	    rb_str_set_len(res, plen - len);
+	    }
+	    CFDataSetLength(data, plen - len);
 	    break;
 
 	  case '@':		/* null fill to absolute position */
-	    len -= RSTRING_LEN(res);
-	    if (len > 0) goto grow;
+	    len -= CFDataGetLength(data);
+	    if (len > 0) {
+		goto grow;
+	    }
 	    len = -len;
-	    if (len > 0) goto shrink;
+	    if (len > 0) {
+		goto shrink;
+	    }
 	    break;
 
 	  case '%':
@@ -884,7 +885,7 @@
 		    rb_raise(rb_eRangeError, "pack(U): value out of range");
 		}
 		le = rb_uv_to_utf8(buf, l);
-		rb_str_buf_cat(res, (char*)buf, le);
+		CFDataAppendBytes(data, (const UInt8 *)buf, le);
 	    }
 	    break;
 
@@ -895,18 +896,22 @@
 	    ptr = RSTRING_PTR(from);
 	    plen = RSTRING_LEN(from);
 
-	    if (len <= 2)
+	    if (len <= 2) {
 		len = 45;
-	    else
+	    }
+	    else {
 		len = len / 3 * 3;
+	    }
 	    while (plen > 0) {
 		long todo;
 
-		if (plen > len)
+		if (plen > len) {
 		    todo = len;
-		else
+		}
+		else {
 		    todo = plen;
-		encodes(res, ptr, todo, type);
+		}
+		encodes(data, ptr, todo, type);
 		plen -= todo;
 		ptr += todo;
 	    }
@@ -914,9 +919,10 @@
 
 	  case 'M':		/* quoted-printable encoded string */
 	    from = rb_obj_as_string(NEXTFROM);
-	    if (len <= 1)
+	    if (len <= 1) {
 		len = 72;
-	    qpencode(res, from, len);
+	    }
+	    qpencode(data, from, len);
 	    break;
 
 	  case 'P':		/* pointer to packed byte string */
@@ -945,14 +951,14 @@
 		}
 		rb_ary_push(associates, from);
 		rb_obj_taint(from);
-		rb_str_buf_cat(res, (char*)&t, sizeof(char*));
+		CFDataAppendBytes(data, (const UInt8 *)&t, sizeof(char*));
 	    }
 	    break;
 
 	  case 'w':		/* BER compressed integer  */
 	    while (len-- > 0) {
 		unsigned long ul;
-		VALUE buf = rb_str_new(0, 0);
+		CFMutableDataRef bufdata = CFDataCreateMutable(NULL, 0);
 		char c, *bufs, *bufe;
 
 		from = NEXTFROM;
@@ -961,40 +967,41 @@
 		    while (TYPE(from) == T_BIGNUM) {
 			from = rb_big_divmod(from, big128);
 			c = NUM2INT(RARRAY_AT(from, 1)) | 0x80; /* mod */
-			rb_str_buf_cat(buf, &c, sizeof(char));
+			CFDataAppendBytes(bufdata, (const UInt8 *)&c, sizeof(char));
 			from = RARRAY_AT(from, 0); /* div */
 		    }
 		}
 
-		{
-		    long l = NUM2LONG(from);
-		    if (l < 0) {
-			rb_raise(rb_eArgError, "can't compress negative numbers");
-		    }
-		    ul = l;
+		long l = NUM2LONG(from);
+		if (l < 0) {
+		    rb_raise(rb_eArgError, "can't compress negative numbers");
 		}
+		ul = l;
 
 		while (ul) {
 		    c = ((ul & 0x7f) | 0x80);
-		    rb_str_buf_cat(buf, &c, sizeof(char));
+		    CFDataAppendBytes(bufdata, (const UInt8 *)&c, sizeof(char));
 		    ul >>=  7;
 		}
 
-		if (RSTRING_BYTELEN(buf)) {
-		    bufs = RSTRING_BYTEPTR(buf);
-		    bufe = bufs + RSTRING_BYTELEN(buf) - 1;
+		if (CFDataGetLength(bufdata) > 0) {
+		    UInt8 *buf_beg = CFDataGetMutableBytePtr(bufdata);
+		    bufs = (char *)buf_beg;
+		    bufe = bufs + CFDataGetLength(bufdata) - 1;
 		    *bufs &= 0x7f; /* clear continue bit */
 		    while (bufs < bufe) { /* reverse */
 			c = *bufs;
 			*bufs++ = *bufe;
 			*bufe-- = c;
 		    }
-		    rb_str_buf_cat(res, RSTRING_BYTEPTR(buf), RSTRING_BYTELEN(buf));
+		    CFDataAppendBytes(data, buf_beg, CFDataGetLength(bufdata));
 		}
 		else {
 		    c = 0;
-		    rb_str_buf_cat(res, &c, sizeof(char));
+		    CFDataAppendBytes(data, (const UInt8 *)&c, sizeof(char));
 		}
+
+		CFRelease(bufdata);
 	    }
 	    break;
 
@@ -1004,9 +1011,10 @@
     }
 
     if (associates) {
-	rb_str_associate(res, associates);
+	rb_str_associate(bres, associates);
     }
-    return res;
+
+    return bres;
 }
 
 static const char uu_table[] =
@@ -1015,7 +1023,7 @@
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 static void
-encodes(VALUE str, const char *s, long len, int type)
+encodes(CFMutableDataRef data, const char *s, long len, int type)
 {
     char *buff = ALLOCA_N(char, len * 4 / 3 + 6);
     long i = 0;
@@ -1050,13 +1058,13 @@
 	buff[i++] = padding;
     }
     buff[i++] = '\n';
-    rb_str_buf_cat(str, buff, i);
+    CFDataAppendBytes(data, (const UInt8 *)buff, i);
 }
 
 static const char hex_table[] = "0123456789ABCDEF";
 
 static void
-qpencode(VALUE str, VALUE from, long len)
+qpencode(CFMutableDataRef data, VALUE from, long len)
 {
     char buff[1024];
     long i = 0, n = 0, prev = EOF;
@@ -1094,7 +1102,7 @@
             prev = '\n';
         }
 	if (i > 1024 - 5) {
-	    rb_str_buf_cat(str, buff, i);
+	    CFDataAppendBytes(data, (const UInt8 *)buff, i);
 	    i = 0;
 	}
 	s++;
@@ -1104,7 +1112,7 @@
 	buff[i++] = '\n';
     }
     if (i > 0) {
-	rb_str_buf_cat(str, buff, i);
+	CFDataAppendBytes(data, (const UInt8 *)buff, i);
     }
 }
 
@@ -1151,12 +1159,7 @@
 static VALUE
 infected_str_new(const char *ptr, long len, VALUE str)
 {
-    VALUE s = rb_str_new(ptr, len);
-
-#if !WITH_OBJC
-    OBJ_INFECT(s, str);
-#endif
-    return s;
+    return rb_str_new(ptr, len);
 }
 
 /*
@@ -1424,14 +1427,19 @@
 		if (p[-1] == '*' || len > (send - s) * 8)
 		    len = (send - s) * 8;
 		bits = 0;
-		UNPACK_PUSH(bitstr = rb_str_new(0, len));
-		t = RSTRING_BYTEPTR(bitstr);
+		bitstr = rb_bytestring_new();
+		rb_bytestring_resize(bitstr, len);
+		UNPACK_PUSH(bitstr);
+		t = (char *)rb_bytestring_byte_pointer(bitstr);
 		for (i=0; i<len; i++) {
-		    if (i & 7) bits >>= 1;
-		    else bits = *s++;
+		    if (i & 7) {
+			bits >>= 1;
+		    }
+		    else {
+			bits = *s++;
+		    }
 		    *t++ = (bits & 1) ? '1' : '0';
 		}
-		RSTRING_SYNC(bitstr);
 	    }
 	    break;
 
@@ -1445,14 +1453,19 @@
 		if (p[-1] == '*' || len > (send - s) * 8)
 		    len = (send - s) * 8;
 		bits = 0;
-		UNPACK_PUSH(bitstr = rb_str_new(0, len));
-		t = RSTRING_BYTEPTR(bitstr);
+		bitstr = rb_bytestring_new();
+		rb_bytestring_resize(bitstr, len);
+		UNPACK_PUSH(bitstr);
+		t = (char *)rb_bytestring_byte_pointer(bitstr);
 		for (i=0; i<len; i++) {
-		    if (i & 7) bits <<= 1;
-		    else bits = *s++;
+		    if (i & 7) {
+			bits <<= 1;
+		    }
+		    else {
+			bits = *s++;
+		    }
 		    *t++ = (bits & 128) ? '1' : '0';
 		}
-		RSTRING_SYNC(bitstr);
 	    }
 	    break;
 
@@ -1466,16 +1479,19 @@
 		if (p[-1] == '*' || len > (send - s) * 2)
 		    len = (send - s) * 2;
 		bits = 0;
-		UNPACK_PUSH(bitstr = rb_str_new(0, len));
-		t = RSTRING_BYTEPTR(bitstr);
+		bitstr = rb_bytestring_new();
+		rb_bytestring_resize(bitstr, len);
+		UNPACK_PUSH(bitstr);
+		t = (char *)rb_bytestring_byte_pointer(bitstr);
 		for (i=0; i<len; i++) {
-		    if (i & 1)
+		    if (i & 1) {
 			bits >>= 4;
-		    else
+		    }
+		    else {
 			bits = *s++;
+		    }
 		    *t++ = hexdigits[bits & 15];
 		}
-		RSTRING_SYNC(bitstr);
 	    }
 	    break;
 
@@ -1489,16 +1505,19 @@
 		if (p[-1] == '*' || len > (send - s) * 2)
 		    len = (send - s) * 2;
 		bits = 0;
-		UNPACK_PUSH(bitstr = rb_str_new(0, len));
-		t = RSTRING_BYTEPTR(bitstr);
+		bitstr = rb_bytestring_new();
+		rb_bytestring_resize(bitstr, len);
+		UNPACK_PUSH(bitstr);
+		t = (char *)rb_bytestring_byte_pointer(bitstr);
 		for (i=0; i<len; i++) {
-		    if (i & 1)
+		    if (i & 1) {
 			bits <<= 4;
-		    else
+		    }
+		    else {
 			bits = *s++;
+		    }
 		    *t++ = hexdigits[(bits >> 4) & 15];
 		}
-		RSTRING_SYNC(bitstr);
 	    }
 	    break;
 
@@ -1744,9 +1763,11 @@
 
 	  case 'u':
 	    {
-		VALUE buf = infected_str_new(0, (send - s)*3/4, str);
-		char *ptr = RSTRING_BYTEPTR(buf);
+		VALUE buf = rb_bytestring_new();
+		rb_bytestring_resize(buf, (send - s)*3/4);
+		char *ptr = (char *)rb_bytestring_byte_pointer(buf);
 		long total = 0;
+		const long buflen = rb_bytestring_length(buf);
 
 		while (s < send && *s > ' ' && *s < 'a') {
 		    long a,b,c,d;
@@ -1755,30 +1776,38 @@
 		    hunk[3] = '\0';
 		    len = (*s++ - ' ') & 077;
 		    total += len;
-		    if (total > RSTRING_BYTELEN(buf)) {
-			len -= total - RSTRING_BYTELEN(buf);
-			total = RSTRING_BYTELEN(buf);
+		    if (total > buflen) {
+			len -= total - buflen;
+			total = buflen;
 		    }
 
 		    while (len > 0) {
 			long mlen = len > 3 ? 3 : len;
 
-			if (s < send && *s >= ' ')
+			if (s < send && *s >= ' ') {
 			    a = (*s++ - ' ') & 077;
-			else
+			}
+			else {
 			    a = 0;
-			if (s < send && *s >= ' ')
+			}
+			if (s < send && *s >= ' ') {
 			    b = (*s++ - ' ') & 077;
-			else
+			}
+			else {
 			    b = 0;
-			if (s < send && *s >= ' ')
+			}
+			if (s < send && *s >= ' ') {
 			    c = (*s++ - ' ') & 077;
-			else
+			}
+			else {
 			    c = 0;
-			if (s < send && *s >= ' ')
+			}
+			if (s < send && *s >= ' ') {
 			    d = (*s++ - ' ') & 077;
-			else
+			}
+			else {
 			    d = 0;
+			}
 			hunk[0] = a << 2 | b >> 4;
 			hunk[1] = b << 4 | c >> 2;
 			hunk[2] = c << 6 | d;
@@ -1786,22 +1815,28 @@
 			ptr += mlen;
 			len -= mlen;
 		    }
-		    if (*s == '\r') s++;
-		    if (*s == '\n') s++;
-		    else if (s < send && (s+1 == send || s[1] == '\n'))
+		    if (*s == '\r') {
+			s++;
+		    }
+		    if (*s == '\n') {
+			s++;
+		    }
+		    else if (s < send && (s+1 == send || s[1] == '\n')) {
 			s += 2;	/* possible checksum byte */
+		    }
 		}
 
-		rb_str_set_len(buf, total);
-		RSTRING_SYNC(buf);
+		rb_bytestring_resize(buf, total);
 		UNPACK_PUSH(buf);
 	    }
 	    break;
 
 	  case 'm':
 	    {
-		VALUE buf = infected_str_new(0, (send - s)*3/4, str);
-		char *ptr = RSTRING_BYTEPTR(buf);
+		VALUE buf = rb_bytestring_new();
+		rb_bytestring_resize(buf, (send - s)*3/4);
+		char *ptr = (char *)rb_bytestring_byte_pointer(buf);
+		char *ptr_beg = ptr;
 		int a = -1,b = -1,c = 0,d;
 		static int first = 1;
 		static int b64_xtable[256];
@@ -1836,23 +1871,25 @@
 		    *ptr++ = c << 6 | d;
 		}
 		if (a != -1 && b != -1) {
-		    if (c == -1 && *s == '=')
+		    if (c == -1 && *s == '=') {
 			*ptr++ = a << 2 | b >> 4;
+		    }
 		    else if (c != -1 && *s == '=') {
 			*ptr++ = a << 2 | b >> 4;
 			*ptr++ = b << 4 | c >> 2;
 		    }
 		}
-		rb_str_set_len(buf, ptr - RSTRING_BYTEPTR(buf));
-		RSTRING_SYNC(buf);
+		rb_bytestring_resize(buf, ptr - ptr_beg);
 		UNPACK_PUSH(buf);
 	    }
 	    break;
 
 	  case 'M':
 	    {
-		VALUE buf = infected_str_new(0, send - s, str);
-		char *ptr = RSTRING_BYTEPTR(buf);
+		VALUE buf = rb_bytestring_new();
+		rb_bytestring_resize(buf, send - s);
+		char *ptr = (char *)rb_bytestring_byte_pointer(buf);
+		char *ptr_beg = ptr;
 		int c1, c2;
 
 		while (s < send) {
@@ -1872,8 +1909,7 @@
 		    }
 		    s++;
 		}
-		rb_str_set_len(buf, ptr - RSTRING_BYTEPTR(buf));
-		RSTRING_SYNC(buf);
+		rb_bytestring_resize(buf, ptr - ptr_beg);
 		UNPACK_PUSH(buf);
 	    }
 	    break;
@@ -1905,7 +1941,6 @@
 		s += sizeof(char *);
 
 		if (t) {
-#if WITH_OBJC
 		    VALUE a;
 		    long i, count;
 		    if (!(a = rb_str_associated(str))) {
@@ -1928,31 +1963,6 @@
 		    if (i == count) {
 			rb_raise(rb_eArgError, "non associated pointer");
 		    }
-#else
-		    VALUE a, *p, *pend;
-
-		    if (!(a = rb_str_associated(str))) {
-			rb_raise(rb_eArgError, "no associated pointer");
-		    }
-		    p = RARRAY_PTR(a);
-		    pend = p + RARRAY_LEN(a);
-		    while (p < pend) {
-			if (TYPE(*p) == T_STRING && RSTRING_BYTEPTR(*p) == t) {
-			    if (len < RSTRING_BYTELEN(*p)) {
-				tmp = rb_tainted_str_new(t, len);
-				rb_str_associate(tmp, a);
-			    }
-			    else {
-				tmp = *p;
-			    }
-			    break;
-			}
-			p++;
-		    }
-		    if (p == pend) {
-			rb_raise(rb_eArgError, "non associated pointer");
-		    }
-#endif
 		}
 		else {
 		    tmp = Qnil;
@@ -1974,8 +1984,7 @@
 		    memcpy(&t, s, sizeof(char *));
 		    s += sizeof(char *);
 
-		    if (t) {
-#if WITH_OBJC
+		    if (t != NULL) {
 			VALUE a;
 			long i, count;
 
@@ -1993,25 +2002,6 @@
 			if (i == count) {
 			    rb_raise(rb_eArgError, "non associated pointer");
 			}
-#else
-			VALUE a, *p, *pend;
-
-			if (!(a = rb_str_associated(str))) {
-			    rb_raise(rb_eArgError, "no associated pointer");
-			}
-			p = RARRAY_PTR(a);
-			pend = p + RARRAY_LEN(a);
-			while (p < pend) {
-			    if (TYPE(*p) == T_STRING && RSTRING_PTR(*p) == t) {
-				tmp = *p;
-				break;
-			    }
-			    p++;
-			}
-			if (p == pend) {
-			    rb_raise(rb_eArgError, "non associated pointer");
-			}
-#endif
 		    }
 		    else {
 			tmp = Qnil;

Modified: MacRuby/branches/experimental/parse.y
===================================================================
--- MacRuby/branches/experimental/parse.y	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/parse.y	2009-03-16 02:26:09 UTC (rev 929)
@@ -4927,7 +4927,6 @@
 static VALUE
 lex_get_str(struct parser_params *parser, VALUE s)
 {
-#if WITH_OBJC
     long beg, len, n;
     CFRange search_range;  
     VALUE v;
@@ -4935,15 +4934,16 @@
     beg = 0; 
     n = CFStringGetLength((CFStringRef)s);
     if (lex_gets_ptr > 0) {
-	if (n == lex_gets_ptr)
+	if (n == lex_gets_ptr) {
 	    return Qnil;
+	}
 	beg += lex_gets_ptr;
     }
     if (CFStringFindCharacterFromSet((CFStringRef)s, 
-	CFCharacterSetGetPredefined(kCFCharacterSetNewline),
-	CFRangeMake(beg, n - beg),
-	0,
-	&search_range)) {
+		CFCharacterSetGetPredefined(kCFCharacterSetNewline),
+		CFRangeMake(beg, n - beg),
+		0,
+		&search_range)) {
 	lex_gets_ptr = search_range.location + 1;
 	len = search_range.location - beg;
     }
@@ -4955,24 +4955,6 @@
 	CFRangeMake(beg, lex_gets_ptr - beg));
     CFMakeCollectable((CFTypeRef)v);
     return v;
-#else
-    const char *cptr, *beg, *end, *pend;
-    long clen;
-
-    cptr = beg = RSTRING_BYTEPTR(s);
-    clen = RSTRING_BYTELEN(s);
-    if (lex_gets_ptr) {
-	if (clen == lex_gets_ptr) return Qnil;
-	beg += lex_gets_ptr;
-    }
-    pend = cptr + clen;
-    end = beg;
-    while (end < pend) {
-	if (*end++ == '\n') break;
-    }
-    lex_gets_ptr = end - cptr;
-    return rb_enc_str_new(beg, end - beg, rb_enc_get(s));
-#endif
 }
 
 static VALUE
@@ -5549,10 +5531,6 @@
 dispose_string(VALUE str)
 {
     /* TODO: should use another API? */
-#if !WITH_OBJC
-    if (RBASIC(str)->flags & RSTRING_NOEMBED)
-	xfree(RSTRING_BYTEPTR(str));
-#endif
     rb_gc_force_recycle(str);
 }
 
@@ -5844,8 +5822,8 @@
 #endif
     line = here->nd_orig;
     lex_lastline = line;
-    lex_pbeg = RSTRING_BYTEPTR(line);
-    lex_pend = lex_pbeg + RSTRING_BYTELEN(line);
+    lex_pbeg = RSTRING_PTR(line);
+    lex_pend = lex_pbeg + RSTRING_LEN(line);
     lex_p = lex_pbeg + here->nd_nth;
     heredoc_end = ruby_sourceline;
     ruby_sourceline = nd_line(here);
@@ -6093,16 +6071,9 @@
 {
     VALUE name = 0, val = 0;
     const char *beg, *end, *vbeg, *vend;
-#if WITH_OBJC
-# define str_copy(_s, _p, _n) ((_s) \
+#define str_copy(_s, _p, _n) ((_s) \
 	? CFStringPad((CFMutableStringRef)_s, CFMakeCollectable(CFStringCreateWithCString(NULL, _p, kCFStringEncodingUTF8)), _n, 0) \
 	: ((_s) = STR_NEW((_p), (_n)))) 
-#else
-# define str_copy(_s, _p, _n) ((_s) \
-	? (rb_str_resize((_s), (_n)), \
-	   MEMCPY(RSTRING_BYTEPTR(_s), (_p), char, (_n)), (_s)) \
-	: ((_s) = STR_NEW((_p), (_n))))
-#endif
 
     if (len <= 7) return Qfalse;
     if (!(beg = magic_comment_marker(str, len))) return Qfalse;
@@ -7739,17 +7710,6 @@
 static int
 literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
 {
-#if !WITH_OBJC
-    if (!rb_enc_compatible(head, tail)) {
-	compile_error(PARSER_ARG "string literal encodings differ (%s / %s)",
-		      rb_enc_name(rb_enc_get(head)),
-		      rb_enc_name(rb_enc_get(tail)));
-	rb_str_resize(head, 0);
-	rb_str_resize(tail, 0);
-	return 0;
-    }
-#endif
-    RSTRING_SYNC(head);
     rb_str_buf_append(head, tail);
     return 1;
 }
@@ -9573,24 +9533,8 @@
 ID
 rb_intern_str(VALUE str)
 {
-    ID id;
-
-#if WITH_OBJC
     const char *s = RSTRING_PTR(str);
-    id = rb_intern3(s, strlen(s), NULL);
-#else
-    rb_encoding *enc;
-    enc = rb_enc_get(str);
-    if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
-	enc = rb_usascii_encoding();
-    }
-    else {
-	enc = rb_enc_get(str);
-    }
-    id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
-    RB_GC_GUARD(str);
-#endif
-    return id;
+    return rb_intern3(s, strlen(s), NULL);
 }
 
 VALUE
@@ -9605,12 +9549,7 @@
 	    if (op_tbl[i].token == id) {
 		VALUE str = global_symbols.op_sym[i];
 		if (!str) {
-#if WITH_OBJC
 		    str = rsymbol_new(op_tbl[i].name, strlen(op_tbl[i].name), op_tbl[i].token);
-#else
-		    str = rb_usascii_str_new2(op_tbl[i].name);
-		    OBJ_FREEZE(str);
-#endif
 		    global_symbols.op_sym[i] = str;
 		}
 		return str;
@@ -9618,20 +9557,12 @@
 	}
     }
 
-#if WITH_OBJC
     data = (VALUE)CFDictionaryGetValue(
 	(CFDictionaryRef)global_symbols.id_str,
 	(const void *)id);
-    if (data != 0)
+    if (data != 0) {
 	return data;
-#else
-    if (st_lookup(global_symbols.id_str, id, &data)) {
-        VALUE str = (VALUE)data;
-        if (RBASIC(str)->klass == 0)
-            RBASIC(str)->klass = rb_cString;
-	return str;
     }
-#endif
 
     if (is_attrset_id(id)) {
 	ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
@@ -9644,36 +9575,17 @@
 	str = rb_str_dup(str);
 	rb_str_cat(str, "=", 1);
 	rb_intern_str(str);
-#if WITH_OBJC
 	data = (VALUE)CFDictionaryGetValue(
 	    (CFDictionaryRef)global_symbols.id_str,
 	    (const void *)id);
-	if (data != 0)
+	if (data != 0) {
 	    return data;
-#else
-	if (st_lookup(global_symbols.id_str, id, &data)) {
-            VALUE str = (VALUE)data;
-            if (RBASIC(str)->klass == 0)
-                RBASIC(str)->klass = rb_cString;
-            return str;
-        }
-#endif
+	}
     }
     return 0;
 }
 
-#if !WITH_OBJC
 const char *
-rb_id2name(ID id)
-{
-    VALUE str = rb_id2str(id);
-
-    if (!str) return 0;
-    return RSTRING_PTR(str);
-}
-#endif
-
-const char *
 ruby_node_name(int node)
 {
     switch (node) {
@@ -9684,15 +9596,6 @@
     }
 }
  
-#if !WITH_OBJC
-static int
-symbols_i(VALUE sym, ID value, VALUE ary)
-{
-    rb_ary_push(ary, ID2SYM(value));
-    return ST_CONTINUE;
-}
-#endif
-
 /*
  *  call-seq:
  *     Symbol.all_symbols    => array
@@ -9712,23 +9615,18 @@
 VALUE
 rb_sym_all_symbols(void)
 {
-#if WITH_OBJC
     const void **values;
     long count;
     VALUE ary;
 
     ary = rb_ary_new();
     count = CFDictionaryGetCount(global_symbols.id_str);
-    if (count == 0)
+    if (count == 0) {
 	return ary;
+    }
     values = alloca(sizeof(void *) * count);
     CFDictionaryGetKeysAndValues(global_symbols.id_str, NULL, values);
     CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, count);   
-#else
-    VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
-
-    st_foreach(global_symbols.sym_id, symbols_i, ary);
-#endif
     return ary;
 }
 

Modified: MacRuby/branches/experimental/re.c
===================================================================
--- MacRuby/branches/experimental/re.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/re.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -1299,8 +1299,8 @@
     enc = (rb_encoding *)ONIG_ENCODING_ASCII;
 #endif
 
-    r = onig_new(&reg, (UChar* )RSTRING_BYTEPTR(unescaped),
-		 (UChar* )(RSTRING_BYTEPTR(unescaped) + RSTRING_BYTELEN(unescaped)),
+    r = onig_new(&reg, (UChar* )RSTRING_PTR(unescaped),
+		 (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)),
 		 reg->options, (OnigEncoding)enc,
 		 OnigDefaultSyntax, &einfo);
     if (r) {
@@ -2943,7 +2943,6 @@
 #endif
     const char *s, *send;
     char *t;
-    VALUE tmp;
     int c, clen;
 #if WITH_OBJC
     int ascii_only = 0;
@@ -2985,35 +2984,18 @@
     }
     return str;
 
+    char *t_beg;
+
   meta_found:
-    tmp = rb_str_new(0, RSTRING_LEN(str)*2);
-#if !WITH_OBJC
-    if (ascii_only) {
-        rb_enc_associate(tmp, rb_usascii_encoding());
-    }
-    else {
-        rb_enc_copy(tmp, str);
-    }
-#endif
-    t = RSTRING_BYTEPTR(tmp);
+    t_beg = (char *)alloca(RSTRING_LEN(str) * 2);
+    t = t_beg;
     /* copy upto metacharacter */
     memcpy(t, RSTRING_PTR(str), s - RSTRING_PTR(str));
     t += s - RSTRING_PTR(str);
 
     while (s < send) {
-#if WITH_OBJC
 	c = *s;
 	clen = 1;
-#else
-        c = rb_enc_ascget(s, send, &clen, enc);
-	if (c == -1) {
-	    int n = mbclen(s, send, enc);
-
-	    while (n--)
-		*t++ = *s++;
-	    continue;
-	}
-#endif
         s += clen;
 	switch (c) {
 	  case '[': case ']': case '{': case '}':
@@ -3050,12 +3032,8 @@
 	}
 	*t++ = c;
     }
-    rb_str_resize(tmp, t - RSTRING_BYTEPTR(tmp));
-    RSTRING_SYNC(tmp);
-#if !WITH_OBJC
-    OBJ_INFECT(tmp, str);
-#endif
-    return tmp;
+
+    return rb_str_new(t, t - t_beg);
 }
 
 

Modified: MacRuby/branches/experimental/ruby.c
===================================================================
--- MacRuby/branches/experimental/ruby.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/ruby.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -1053,26 +1053,34 @@
 	    c = rb_io_getbyte(f, 0);
 	    if (c == INT2FIX('!')) {
 		line = rb_io_gets(f, 0);
-		if (NIL_P(line))
+		if (NIL_P(line)) {
 		    return 0;
+		}
+		assert(*(VALUE *)line == rb_cByteString);
 
 		if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) {
 		    /* not ruby script, kick the program */
 		    char **argv;
 		    char *path;
-		    char *pend = RSTRING_BYTEPTR(line) + RSTRING_BYTELEN(line);
+		    char *pend;
 
-		    p = RSTRING_BYTEPTR(line);	/* skip `#!' */
-		    if (pend[-1] == '\n')
+		    p = (char *)rb_bytestring_byte_pointer(line);
+		    pend = p + rb_bytestring_length(line);
+
+		    if (pend[-1] == '\n') {
 			pend--;	/* chomp line */
-		    if (pend[-1] == '\r')
+		    }
+		    if (pend[-1] == '\r') {
 			pend--;
+		    }
 		    *pend = '\0';
-		    while (p < pend && ISSPACE(*p))
+		    while (p < pend && ISSPACE(*p)) {
 			p++;
+		    }
 		    path = p;	/* interpreter path */
-		    while (p < pend && !ISSPACE(*p))
+		    while (p < pend && !ISSPACE(*p)) {
 			p++;
+		    }
 		    *p++ = '\0';
 		    if (p < pend) {
 			argv = ALLOCA_N(char *, origarg.argc + 3);
@@ -1090,9 +1098,14 @@
 
 	      start_read:
 		p += 4;
-		RSTRING_BYTEPTR(line)[RSTRING_BYTELEN(line) - 1] = '\0';
-		if (RSTRING_BYTEPTR(line)[RSTRING_BYTELEN(line) - 2] == '\r')
-		    RSTRING_BYTEPTR(line)[RSTRING_BYTELEN(line) - 2] = '\0';
+
+		char *linebuf = (char *)rb_bytestring_byte_pointer(line);
+		long linebuflen = rb_bytestring_length(line);
+
+		linebuf[linebuflen - 1] = '\0';
+		if (linebuf[linebuflen - 2] == '\r') {
+		    linebuf[linebuflen - 2] = '\0';
+		}
 		if ((p = strstr(p, " -")) != 0) {
 		    p++;	/* skip space before `-' */
 		    while (*p == '-') {

Modified: MacRuby/branches/experimental/string.c
===================================================================
--- MacRuby/branches/experimental/string.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/string.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -35,110 +35,8 @@
 VALUE rb_cByteString;
 
 static ptrdiff_t wrappedDataOffset;
+#define WRAPPED_DATA_IV_NAME "wrappedData"
 
-static void *rb_str_cfdata_key;
-
-static inline void
-rb_str_cfdata_set(VALUE str, void *cfdata)
-{
-    rb_objc_set_associative_ref((void *)str, &rb_str_cfdata_key,
-	    cfdata);
-}
-
-static inline void *
-rb_str_cfdata2(VALUE str) 
-{
-    return rb_objc_get_associative_ref((void *)str, &rb_str_cfdata_key);
-}
-
-static inline bool
-rb_objc_str_is_bytestring(VALUE str)
-{
-    return rb_str_cfdata2(str) != NULL;
-}
-
-static void *
-rb_str_cfdata(VALUE str)
-{
-    void *cfdata;
-
-    assert(str != 0);
-
-    cfdata = rb_str_cfdata2(str);
-    if (cfdata == NULL) {
-	CFMutableDataRef mdata;
-	long len;
-
-	if (CFStringGetLength((CFStringRef)str) == 0) {
-	    mdata = CFDataCreateMutable(NULL, 0);
-	}
-	else {
-	    CFDataRef data;
-	    data = CFStringCreateExternalRepresentation(NULL,
-		    (CFStringRef)str, kCFStringEncodingUTF8, 0);
-	    if (data == NULL)
-		return NULL;
-	    mdata = CFDataCreateMutableCopy(NULL, 0, data);
-	    len = CFDataGetLength(data);
-	    /* This is a hack to make sure a sentinel byte is created at the 
-	     * end of the buffer. 
-	     */
-	    CFDataSetLength(mdata, len + 1); 
-	    CFDataSetLength(mdata, len);
-	    CFRelease((CFTypeRef)data);
-	}
-	cfdata = (void *)mdata;
-	rb_str_cfdata_set(str, cfdata);
-	CFMakeCollectable(mdata);
-    }
-    return cfdata;    
-}
-
-char *
-rb_str_byteptr(VALUE str)
-{
-    return (char *)CFDataGetMutableBytePtr(
-	(CFMutableDataRef)rb_str_cfdata(str));
-}
-
-long
-rb_str_bytelen(VALUE str)
-{
-    return CFDataGetLength((CFDataRef)rb_str_cfdata(str));
-}
-
-void
-rb_str_bytesync(VALUE str)
-{
-    void *cfdata;
-
-    cfdata = rb_str_cfdata2(str);
-    if (cfdata != NULL) {
-	CFDataRef data;
-	CFIndex datalen;
-	const UInt8 *dataptr;
-	CFStringRef bytestr;
-
-	data = (CFDataRef)cfdata;
-	datalen = CFDataGetLength(data);
-	dataptr = CFDataGetBytePtr(data);
-	bytestr = CFStringCreateWithBytesNoCopy(
-		NULL,
-		dataptr,
-		datalen,
-		kCFStringEncodingUTF8,
-		false,
-		kCFAllocatorNull);
-	if (bytestr != NULL) {
-	    CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)bytestr);
-	    if (CFStringGetLength(bytestr) == datalen) {
-		rb_str_cfdata_set(str, NULL);
-	    }
-	    CFRelease(bytestr);
-	}
-    }
-}
-
 VALUE
 rb_str_freeze(VALUE str)
 {
@@ -146,12 +44,6 @@
     return str;
 }
 
-static VALUE
-rb_str_bytestring_m(VALUE str, SEL sel)
-{
-    return rb_objc_str_is_bytestring(str) ? Qtrue : Qfalse;
-}
-
 #define is_ascii_string(str) (1)
 #define is_broken_string(str) (0)
 #define STR_ENC_GET(str) (NULL)
@@ -176,8 +68,10 @@
     if (klass != 0 
 	&& klass != rb_cNSString 
 	&& klass != rb_cNSMutableString
-	&& klass != rb_cSymbol)
+	&& klass != rb_cSymbol
+	&& klass != rb_cByteString) {
 	*(Class *)str = (Class)klass;
+    }
     CFMakeCollectable((CFTypeRef)str);
 
     return (VALUE)str;
@@ -209,28 +103,6 @@
 }
 
 static VALUE
-rb_str_new_bytestring_m(VALUE rcv, SEL sel, VALUE data)
-{
-    VALUE str = str_alloc(0);
-    rb_str_cfdata_set(str, (void *)data);
-    return str;
-}
-
-static void
-rb_objc_str_set_bytestring(VALUE str, const char *dataptr, long datalen)
-{
-    CFMutableDataRef data;
-
-    assert(dataptr != NULL);
-    assert(datalen > 0);
-
-    data = CFDataCreateMutable(NULL, 0);
-    CFDataAppendBytes(data, (const UInt8 *)dataptr, datalen);
-    rb_str_cfdata_set(str, data);
-    CFMakeCollectable(data);
-}
-
-static VALUE
 str_new(VALUE klass, const char *ptr, long len)
 {
     VALUE str;
@@ -239,41 +111,33 @@
 	rb_raise(rb_eArgError, "negative string size (or size too big)");
     }
 
-    str = str_alloc(klass);
-    bool need_padding = len > 0;
     if (ptr != NULL && len > 0) {
-	long slen;
-	slen = strlen(ptr);
+	const long slen = strlen(ptr);
 
 	if (slen == len) {
+	    str = str_alloc(klass);
 	    CFStringAppendCString((CFMutableStringRef)str, ptr, 
 		    kCFStringEncodingUTF8);
-	    need_padding = false;
-	    if (CFStringGetLength((CFStringRef)str) != len)
-		rb_objc_str_set_bytestring(str, ptr, len);
+	    if (CFStringGetLength((CFStringRef)str) != len) {
+		// XXX could this happen?
+		abort();
+	    }
 	}
 	else {
-	    if (slen == 0 || len < slen) {
-		CFStringRef substr;
-
-		substr = CFStringCreateWithBytes(NULL, (const UInt8 *)ptr, 
-			len, kCFStringEncodingUTF8, false);
-
-		if (substr != NULL) {
-		    CFStringAppend((CFMutableStringRef)str, substr);
-		    CFRelease(substr);		
-		}
-		else {
-		    rb_objc_str_set_bytestring(str, ptr, len);
-		}
-	    }
-	    else {
-		rb_objc_str_set_bytestring(str, ptr, len);
-	    }
+	    str = rb_bytestring_new();
+	    CFMutableDataRef data = rb_bytestring_wrapped_data(str);
+	    CFDataAppendBytes(data, (const UInt8 *)ptr, len);
 	}
     }
-    if (need_padding)
-	CFStringPad((CFMutableStringRef)str, CFSTR(" "), len, 0);
+    else {
+	if (len == 0) {
+	    str = str_alloc(klass);
+	}
+	else {
+	    str = rb_bytestring_new();
+	    rb_bytestring_resize(str, len);
+	}
+    }
 
     return str;
 }
@@ -367,27 +231,26 @@
 VALUE
 rb_str_buf_new(long capa)
 {
-    VALUE str = str_alloc(rb_cString);
-
-    return str;
+    return rb_bytestring_new();
 }
 
 VALUE
 rb_str_buf_new2(const char *ptr)
 {
-    VALUE str;
+    VALUE str = rb_bytestring_new();
     long len = strlen(ptr);
-
-    str = rb_str_buf_new(len);
-    rb_str_buf_cat(str, ptr, len);
-
+    if (ptr != NULL && len > 0) {
+	CFDataAppendBytes(rb_bytestring_wrapped_data(str), (const UInt8 *)ptr, len);
+    }
     return str;
 }
 
 VALUE
 rb_str_tmp_new(long len)
 {
-    return str_new(0, 0, len);
+    VALUE str = rb_bytestring_new();
+    rb_bytestring_resize(str, len);
+    return str;
 }
 
 VALUE
@@ -410,7 +273,7 @@
 {
     VALUE str;
 
-    if (TYPE(obj) == T_STRING) {
+    if (TYPE(obj) == T_STRING || TYPE(obj) == T_SYMBOL) {
 	return obj;
     }
     //str = rb_funcall(obj, id_to_s, 0);
@@ -430,21 +293,21 @@
 rb_str_dup_imp(VALUE str, SEL sel)
 {
     VALUE dup;
-    void *data;
 
+#if 0
+    if (RSTRING_LEN(str) == 0) {
+	return str_alloc(0);
+    }
     dup = (VALUE)CFStringCreateMutableCopy(NULL, 0, (CFStringRef)str);
+    CFMakeCollectable((CFTypeRef)dup);
+#else
+    dup = (VALUE)objc_msgSend((id)str, selMutableCopy);
+#endif
 
-    data = rb_str_cfdata2(str);
-    if (data != NULL) {
-	rb_str_cfdata_set(dup, data);
-    }
-
     if (OBJ_TAINTED(str)) {
 	OBJ_TAINT(dup);
     }
 
-    CFMakeCollectable((CFTypeRef)dup);
-
     return dup;
 }
 
@@ -524,7 +387,8 @@
 static VALUE
 rb_str_bytesize(VALUE str, SEL sel)
 {
-    return INT2NUM(rb_str_bytelen(str));
+    // TODO
+    abort();
 }
 
 /*
@@ -625,10 +489,15 @@
 static inline void
 str_modifiable(VALUE str)
 {
-    bool __CFStringIsMutable(void *);
-    if (!__CFStringIsMutable((void *)str)) 
-	rb_raise(rb_eRuntimeError, "can't modify immutable string");
-    if (OBJ_FROZEN(str)) rb_error_frozen("string");
+    if (*(VALUE *)str == rb_cCFString) {
+	bool __CFStringIsMutable(void *);
+	if (!__CFStringIsMutable((void *)str)) {
+	    rb_raise(rb_eRuntimeError, "can't modify immutable string");
+	}
+    }
+    if (OBJ_FROZEN(str)) {
+	rb_error_frozen("string");
+    }
     if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
 	rb_raise(rb_eSecurityError, "Insecure: can't modify string");
 }
@@ -639,8 +508,9 @@
 #if WITH_OBJC
     str_modifiable(str);
 #else
-    if (!str_independent(str))
+    if (!str_independent(str)) {
 	str_make_independent(str);
+    }
     ENC_CODERANGE_CLEAR(str);
 #endif
 }
@@ -678,32 +548,40 @@
 const char *
 rb_str_cstr(VALUE ptr)
 {
-    CFDataRef data;
-    const char *cptr;
-   
-    data = (CFDataRef)rb_str_cfdata2(ptr);
-    cptr = NULL;
-    if (data == NULL) {
-	cptr = CFStringGetCStringPtr((CFStringRef)ptr, 0);
-    	if (cptr == NULL) {
-	    long len;
-	    len = CFStringGetLength((CFStringRef)ptr);
-	    if (len == 0)
-		return "";
-	    else 
-		data = (CFDataRef)rb_str_cfdata(ptr);
-	}
+    if (*(VALUE *)ptr == rb_cSymbol) {
+	return RSYMBOL(ptr)->str;
     }
-    return data == NULL ? cptr : (const char *)CFDataGetBytePtr(data);
+    if (*(VALUE *)ptr == rb_cByteString) {
+	return (const char *)rb_bytestring_byte_pointer(ptr);
+    }
+
+    if (RSTRING_LEN(ptr) == 0) {
+	return "";
+    }
+
+    char *cptr = (char *)CFStringGetCStringPtr((CFStringRef)ptr, 0);
+    if (cptr != NULL) {
+	return cptr;
+    }
+
+    // XXX this is quite inefficient, but we don't really have the
+    // choice.
+
+    const long max = CFStringGetMaximumSizeForEncoding(
+	    CFStringGetLength((CFStringRef)ptr),
+	    kCFStringEncodingUTF8);
+
+    cptr = (char *)xmalloc(max + 1);
+    assert(CFStringGetCString((CFStringRef)ptr, cptr,
+		max, kCFStringEncodingUTF8));
+
+    return cptr;
 }
 
 long
 rb_str_clen(VALUE ptr)
 {
-    CFDataRef data = (CFDataRef)rb_str_cfdata2(ptr);
-    return data == NULL 
-	? CFStringGetLength((CFStringRef)ptr) 
-	: CFDataGetLength(data);
+    return CFStringGetLength((CFStringRef)ptr);
 }
 
 char *
@@ -747,58 +625,36 @@
 VALUE
 rb_str_subseq(VALUE str, long beg, long len)
 {
-    CFDataRef data;
     CFMutableStringRef substr;
     long n;
 
-#if 1
-    data = NULL;
     n = CFStringGetLength((CFStringRef)str);
-#else
-    /* the world is not prepared for this yet */
-    data = (CFDataRef)rb_str_cfdata2(str);
-    if (data != NULL) {
-	n = CFDataGetLength(data);
-    }
-    else {
-        n = CFStringGetLength((CFStringRef)str);
-    }
-#endif
 
-    if (beg < 0)
+    if (beg < 0) {
 	beg += n;
-    if (beg > n || beg < 0)
+    }
+    if (beg > n || beg < 0) {
 	return Qnil;
-    if (beg + len > n)
+    }
+    if (beg + len > n) {
 	return (VALUE)CFSTR("");
+    }
 
     substr = CFStringCreateMutable(NULL, 0);
 
-    if (data != NULL) {
-	const UInt8 *bytes;
-	CFMutableDataRef subdata;
-
-	bytes = CFDataGetBytePtr(data);
-	subdata = CFDataCreateMutable(NULL, 0);
-	CFDataAppendBytes(subdata, bytes + beg, len);
-	rb_str_cfdata_set((VALUE)substr, subdata);
-	CFMakeCollectable(subdata);
-
-	RSTRING_SYNC(substr);
+    if (len == 1) {
+	UniChar c = CFStringGetCharacterAtIndex((CFStringRef)str, beg);
+	CFStringAppendCharacters(substr, &c, 1);
     }
     else {
-	if (len == 1) {
-	    UniChar c = CFStringGetCharacterAtIndex((CFStringRef)str, beg);
-	    CFStringAppendCharacters(substr, &c, 1);
-	}
-	else {
-	    UniChar *buffer = alloca(sizeof(UniChar) * len);
-	    CFStringGetCharacters((CFStringRef)str, CFRangeMake(beg, len), 
+	UniChar *buffer = alloca(sizeof(UniChar) * len);
+	CFStringGetCharacters((CFStringRef)str, CFRangeMake(beg, len), 
 		buffer);
-	    CFStringAppendCharacters(substr, buffer, len);
-	}
+	CFStringAppendCharacters(substr, buffer, len);
     }
+
     CFMakeCollectable(substr);
+
     return (VALUE)substr;
 }
 
@@ -846,13 +702,7 @@
     rb_str_modify(str);
     slen = RSTRING_LEN(str);
     if (slen != len) {
-	void *cfdata;
-
 	CFStringPad((CFMutableStringRef)str, CFSTR(" "), len, 0);
-
-	cfdata = rb_str_cfdata2(str);
-	if (cfdata != NULL)
-	    CFDataSetLength((CFMutableDataRef)cfdata, len); 
     }
     return str;
 }
@@ -860,32 +710,37 @@
 static void
 rb_objc_str_cat(VALUE str, const char *ptr, long len, int cfstring_encoding)
 {
-    CFMutableDataRef data;
-
-    data = (CFMutableDataRef)rb_str_cfdata2(str);
-    if (data != NULL) {
+    if (*(VALUE *)str == rb_cByteString) {
+	CFMutableDataRef data = rb_bytestring_wrapped_data(str);
 	CFDataAppendBytes(data, (const UInt8 *)ptr, len);
-	RSTRING_SYNC(str);
     }
     else {
-	long slen;
-	if (ptr[len] != '\0') {
-	    char *p = alloca(len + 1);
-	    memcpy(p, ptr, len);
-	    p[len] = '\0';
-	    ptr = p;
+	long plen = strlen(ptr);
+	if (plen >= len) {
+	    const char *cstr;
+	    if (plen > len) {
+		// Sometimes the given string is bigger than the given length.
+		char *tmp = alloca(len + 1);
+		strncpy(tmp, ptr, len);
+		tmp[len] = '\0';
+		cstr = (const char *)tmp;
+	    }
+	    else {
+		cstr = ptr;
+	    }
+	    CFStringAppendCString((CFMutableStringRef)str, cstr,
+		    cfstring_encoding);
 	}
-	slen = strlen(ptr);
-	if (slen == len) {
-	    CFStringAppendCString((CFMutableStringRef)str, ptr, 
-		cfstring_encoding);
-	}
 	else {
-	    CFStringRef substr = CFStringCreateWithBytes(NULL, 
-		(const UInt8 *)ptr,
-		len, cfstring_encoding, false);
-	    CFStringAppend((CFMutableStringRef)str, substr);
-	    CFRelease(substr);
+	    // Promoting as bytestring!
+	    CFDataRef data = CFStringCreateExternalRepresentation(NULL, (CFStringRef)str,
+		    kCFStringEncodingUTF8, 0);
+	    assert(data != NULL);
+	    CFMutableDataRef mdata = CFDataCreateMutableCopy(NULL, 0, data);
+	    CFRelease(data);
+	    *(VALUE *)str = rb_cByteString;
+	    *(void **)((char *)str + sizeof(void *)) = (void *)mdata;
+	    CFMakeCollectable(mdata);
 	}
     }
 }
@@ -937,37 +792,17 @@
 VALUE
 rb_str_buf_append(VALUE str, VALUE str2)
 {
-    CFMutableDataRef mdata;
-    CFDataRef data;
-    long str2len;
-
     if (TYPE(str2) != T_SYMBOL) {
 	Check_Type(str2, T_STRING);
     }
 
-    str2len = RSTRING_LEN(str2);
+    const char *ptr;
+    long len;
 
-    if (str2len == 0)
-	return str;
+    ptr = RSTRING_PTR(str2);
+    len = RSTRING_LEN(str2);
 
-    data = (CFDataRef)rb_str_cfdata2(str2);
-    if (data != NULL) {
-	mdata = (CFMutableDataRef)rb_str_cfdata(str);
-	CFDataAppendBytes(mdata, CFDataGetBytePtr(data),
-	    CFDataGetLength(data));
-    }
-    else {
-	mdata = (CFMutableDataRef)rb_str_cfdata2(str);
-	if (mdata == NULL) {
-	    CFStringAppend((CFMutableStringRef)str, (CFStringRef)str2);
-	}
-	else {
-	    data = (CFDataRef)rb_str_cfdata(str2);
-	    CFDataAppendBytes(mdata, CFDataGetBytePtr(data), 
-		CFDataGetLength(data));
-	}
-    }
-    RSTRING_SYNC(str);
+    rb_objc_str_cat(str, ptr, len, kCFStringEncodingASCII);
 
     return str;
 }
@@ -1086,9 +921,6 @@
     if (len != RSTRING_LEN(str2)) {
 	return Qfalse;
     }
-    if (rb_str_cfdata2(str1) != NULL || rb_str_cfdata2(str2) != NULL) {
-	return memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0 ? Qtrue : Qfalse;
-    }
     if (!rb_objc_str_is_pure(str2)) {
 	/* This is to work around a strange bug in CFEqual's objc 
 	 * dispatching.
@@ -1120,7 +952,7 @@
 static VALUE
 rb_str_eql(VALUE str1, SEL sel, VALUE str2)
 {
-    if (TYPE(str2) != T_STRING || RSTRING_BYTELEN(str1) != RSTRING_BYTELEN(str2)) {
+    if (TYPE(str2) != T_STRING) {
 	return Qfalse;
     }
 
@@ -2070,7 +1902,6 @@
 	}
 
 	rb_str_modify(str);
-	RSTRING_SYNC(str);
 	rb_str_splice_0(str, BEG(0), END(0) - BEG(0), repl);
 	if (OBJ_TAINTED(repl)) tainted = 1;
 
@@ -2144,7 +1975,9 @@
 	if (NIL_P(hash)) {
 	    StringValue(repl);
 	}
-	if (OBJ_TAINTED(repl)) tainted = 1;
+	if (OBJ_TAINTED(repl)) {
+	    tainted = 1;
+	}
 	break;
       default:
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
@@ -2154,7 +1987,9 @@
     offset=0; n=0;
     beg = rb_reg_search(pat, str, 0, 0);
     if (beg < 0) {
-	if (bang) return Qnil;	/* no match, no substitution */
+	if (bang) {
+	    return Qnil;	/* no match, no substitution */
+	}
 	return rb_str_dup(str);
     }
 
@@ -2178,17 +2013,23 @@
                 val = rb_obj_as_string(val);
             }
 	    str_mod_check(str, sp, slen);
-	    if (bang) str_frozen_check(str);
+	    if (bang) {
+		str_frozen_check(str);
+	    }
 	    if (val == dest) { 	/* paranoid check [ruby-dev:24827] */
 		rb_raise(rb_eRuntimeError, "block should not cheat");
 	    }
-	    if (iter) rb_backref_set(match);
+	    if (iter) {
+		rb_backref_set(match);
+	    }
 	}
 	else {
 	    val = rb_reg_regsub(repl, str, regs, pat);
 	}
 
-	if (OBJ_TAINTED(val)) tainted = 1;
+	if (OBJ_TAINTED(val)) {
+	    tainted = 1;
+	}
 
 	len = beg - offset;	/* copy pre-match substr */
         if (len) {
@@ -2211,24 +2052,26 @@
 	cp = sp + offset;
 	if (offset > slen) break;
 	beg = rb_reg_search(pat, str, offset, 0);
-    } while (beg >= 0);
+    } 
+    while (beg >= 0);
     if (slen > offset) {
         rb_enc_str_buf_cat(dest, cp, slen - offset, str_enc);
     }
     rb_backref_set(match);
     if (bang) {
 	rb_str_modify(str);
-	RSTRING_SYNC(str);
-	RSTRING_SYNC(dest);
 	CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)dest);
     }
     else {
-    	if (!tainted && OBJ_TAINTED(str))
+    	if (!tainted && OBJ_TAINTED(str)) {
 	    tainted = 1;
+	}
 	str = dest;
     }
 
-    if (tainted) OBJ_TAINT(str);
+    if (tainted) {
+	OBJ_TAINT(str);
+    }
     return str;
 }
 
@@ -2307,14 +2150,6 @@
 	return str;
     }
     rb_str_modify(str);
-    CFDataRef data = (CFDataRef)rb_str_cfdata2(str2);
-    if (data != NULL) {
-	CFMutableDataRef mdata;
-       
-	mdata = CFDataCreateMutableCopy(NULL, 0, data);
-	rb_str_cfdata_set(str, mdata);
-	CFMakeCollectable(mdata);
-    }
     CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)str2);
     if (OBJ_TAINTED(str2)) {
 	OBJ_TAINT(str);
@@ -2372,6 +2207,8 @@
 static VALUE
 rb_str_getbyte(VALUE str, SEL sel, VALUE index)
 {
+    // TODO
+#if 0
     long pos = NUM2LONG(index);
     long n = RSTRING_BYTELEN(str);
 
@@ -2383,6 +2220,8 @@
     }
 
     return INT2FIX((unsigned char)RSTRING_BYTEPTR(str)[pos]);
+#endif
+    abort();
 }
 
 /*
@@ -2394,6 +2233,8 @@
 static VALUE
 rb_str_setbyte(VALUE str, SEL sel, VALUE index, VALUE value)
 {
+    // TODO promote to ByteString
+#if 0
     long pos = NUM2LONG(index);
     int byte = NUM2INT(value);
     long n = RSTRING_BYTELEN(str);
@@ -2409,6 +2250,8 @@
     RSTRING_SYNC(str);
 
     return value;
+#endif
+    abort();
 }
 
 
@@ -2600,16 +2443,11 @@
     const char *p, *pend;
     VALUE result;
 
-    if (rb_objc_str_is_bytestring(str)) {
-	p = (const char *)RSTRING_BYTEPTR(str); 
-	pend = (const char *)RSTRING_END(str);
-    }
-    else {
-	p = RSTRING_PTR(str); 
-	pend = p + RSTRING_LEN(str);
-    }
-    if (p == NULL)
+    p = RSTRING_PTR(str); 
+    pend = p + RSTRING_LEN(str);
+    if (p == NULL) {
 	return rb_str_new2("\"\"");
+    }
     result = rb_str_buf_new2("");
     str_cat_char(result, '"', enc);
     while (p < pend) {
@@ -2670,7 +2508,6 @@
 	}
     }
     str_cat_char(result, '"', enc);
-    RSTRING_SYNC(result);
 
     return result;
 }
@@ -2692,17 +2529,10 @@
     long len;
     const char *p, *pend;
     char *q, *qend;
-    VALUE result;
 
     len = 2;			/* "" */
-    if (rb_objc_str_is_bytestring(str)) {
-	p = RSTRING_BYTEPTR(str); 
-	pend = RSTRING_END(str);
-    }
-    else {
-	p = RSTRING_PTR(str); 
-	pend = p + RSTRING_LEN(str);
-    }
+    p = RSTRING_PTR(str); 
+    pend = p + RSTRING_LEN(str);
     while (p < pend) {
 	unsigned char c = *p++;
 	switch (c) {
@@ -2732,10 +2562,12 @@
 	len += strlen(rb_enc_name(enc0));
     }
 
-    result = rb_str_new5(str, 0, len);
-    p = RSTRING_BYTEPTR(str); pend = p + RSTRING_BYTELEN(str);
-    q = RSTRING_BYTEPTR(result); qend = q + len;
+    p = RSTRING_PTR(str);
+    pend = p + RSTRING_LEN(str);
 
+    char *q_beg = q = (char *)alloca(len);
+    qend = q + len;
+
     *q++ = '"';
     while (p < pend) {
 	unsigned char c = *p++;
@@ -2792,13 +2624,11 @@
     *q++ = '"';
     if (!rb_enc_asciicompat(enc0)) {
 	sprintf(q, ".force_encoding(\"%s\")", rb_enc_name(enc0));
-
     }
 
     /* result from dump is ASCII */
 
-    RSTRING_SYNC(result);
-    return result;
+    return rb_str_new2(q_beg);
 }
 
 
@@ -3985,6 +3815,7 @@
 static VALUE
 rb_str_each_byte(VALUE str, SEL sel)
 {
+#if 0 // TODO
     long n, i;
     char *ptr;
 
@@ -3997,6 +3828,8 @@
 	RETURN_IF_BROKEN();
     }
     return str;
+#endif
+    abort();
 }
 
 
@@ -4532,22 +4365,21 @@
  *  <code>[a-zA-Z0-9./]</code>.
  */
 
+extern char *crypt(const char *, const char *);
+
 static VALUE
 rb_str_crypt(VALUE str, SEL sel, VALUE salt)
 {
-    extern char *crypt(const char *, const char *);
-    VALUE result;
-    const char *s;
-
     StringValue(salt);
-    if (RSTRING_BYTELEN(salt) < 2)
+    if (RSTRING_LEN(salt) < 2) {
 	rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
+    }
 
-    s = RSTRING_BYTEPTR(str);
-    if (s == NULL)
-	s = "";
-    result = rb_str_new2(crypt(s, RSTRING_BYTEPTR(salt)));
-    return result;
+    size_t str_len = RSTRING_LEN(str);
+    char *s = alloca(str_len + 1);
+    strncpy(s, RSTRING_PTR(str), str_len + 1);
+
+    return rb_str_new2(crypt(s, RSTRING_PTR(salt)));
 }
 
 
@@ -4618,7 +4450,7 @@
 {
     VALUE vbits;
     int bits;
-    char *ptr, *p, *pend;
+    const char *ptr, *p, *pend;
     long len;
 
     if (argc == 0) {
@@ -4628,8 +4460,8 @@
 	rb_scan_args(argc, argv, "01", &vbits);
 	bits = NUM2INT(vbits);
     }
-    ptr = p = RSTRING_BYTEPTR(str);
-    len = RSTRING_BYTELEN(str);
+    ptr = p = RSTRING_PTR(str);
+    len = RSTRING_LEN(str);
     pend = p + len;
     if (bits >= sizeof(long)*CHAR_BIT) {
 	VALUE sum = INT2FIX(0);
@@ -4847,7 +4679,7 @@
 static VALUE
 rb_str_rpartition(VALUE str, SEL sel, VALUE sep)
 {
-    long pos = RSTRING_BYTELEN(str);
+    long pos = RSTRING_LEN(str);
     int regex = Qfalse;
     long seplen;
 
@@ -4948,25 +4780,8 @@
 static VALUE
 rb_str_force_encoding(VALUE str, SEL sel, VALUE enc)
 {
+    // TODO
     str_modifiable(str);
-#if 0
-    CFDataRef data = rb_str_cfdata2(str);
-    if (data != NULL) {
-	CFStringRef substr;
-	CFStringEncoding *cfenc;
-
-	cfenc = rb_to_encoding(enc);
-	assert(cfenc != NULL);
-
-	substr = CFStringCreateFromExternalRepresentation(NULL, data, *cfenc);
-
-	if (substr) {
-	    CFStringReplaceAll((CFMutableStringRef)str, substr);
-	    CFRelease(substr);
-	    rb_str_cfdata_set(str, NULL);
-	}
-    }
-#endif
     return str;
 }
 
@@ -5332,8 +5147,9 @@
 static UniChar
 imp_rb_symbol_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
 {
-    if (idx < 0 || idx > RSYMBOL(rcv)->len)
+    if (idx < 0 || idx > RSYMBOL(rcv)->len) {
 	rb_bug("[Symbol characterAtIndex:] out of bounds");
+    }
     return RSYMBOL(rcv)->str[idx];
 }
 
@@ -5343,8 +5159,9 @@
 {
     int i;
 
-    if (range.location + range.length > RSYMBOL(rcv)->len)
+    if (range.location + range.length > RSYMBOL(rcv)->len) {
 	rb_bug("[Symbol getCharacters:range:] out of bounds");
+    }
 
     for (i = range.location; i < range.location + range.length; i++) {
 	*buffer = RSYMBOL(rcv)->str[i];
@@ -5355,15 +5172,27 @@
 static bool
 imp_rb_symbol_isEqual(void *rcv, SEL sel, void *other)
 {
-    if (other == NULL)
+    if (other == NULL) {
 	return false;
-    if (rcv == other)
+    }
+    if (rcv == other) {
 	return true;
-    if (!rb_objc_is_kind_of(other, (Class)rb_cNSString))
+    }
+    if (!rb_objc_is_kind_of(other, (Class)rb_cNSString)) {
 	return false;
+    }
     return CFStringCompare((CFStringRef)rcv, (CFStringRef)other, 0) == 0;
 }
 
+static void *
+imp_rb_symbol_mutableCopy(void *rcv, SEL sel)
+{
+    CFMutableStringRef new_str = CFStringCreateMutable(NULL, 0);
+    CFStringAppendCString(new_str, RSYMBOL(rcv)->str, kCFStringEncodingUTF8);
+    CFMakeCollectable(new_str);
+    return new_str;
+}
+
 static void
 install_symbol_primitives(void)
 {
@@ -5373,6 +5202,7 @@
     rb_objc_install_method2(klass, "characterAtIndex:", (IMP)imp_rb_symbol_characterAtIndex);
     rb_objc_install_method2(klass, "getCharacters:range:", (IMP)imp_rb_symbol_getCharactersRange);
     rb_objc_install_method2(klass, "isEqual:", (IMP)imp_rb_symbol_isEqual);
+    rb_objc_install_method2(klass, "mutableCopy", (IMP)imp_rb_symbol_mutableCopy);
 }
 
 #undef INSTALL_METHOD
@@ -5383,7 +5213,7 @@
     return (void **)((char *)bstr + wrappedDataOffset);
 }
 
-inline CFMutableDataRef 
+CFMutableDataRef 
 rb_bytestring_wrapped_data(VALUE bstr)
 {
     void **addr = rb_bytestring_ivar_addr(bstr);
@@ -5394,10 +5224,10 @@
 rb_bytestring_set_wrapped_data(VALUE bstr, CFMutableDataRef data)
 {
     void **addr = rb_bytestring_ivar_addr(bstr);
-    *addr = (void *)data;
+    GC_WB(addr, data);
 }
 
-inline UInt8 *
+UInt8 *
 rb_bytestring_byte_pointer(VALUE bstr)
 {
     return CFDataGetMutableBytePtr(rb_bytestring_wrapped_data(bstr));
@@ -5406,7 +5236,7 @@
 static VALUE
 rb_bytestring_alloc(VALUE klass, SEL sel)
 {
-    VALUE bstr = (VALUE)class_createInstance((Class)rb_cByteString, 0);
+    VALUE bstr = (VALUE)class_createInstance((Class)rb_cByteString, sizeof(void *));
 
     CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
     rb_bytestring_set_wrapped_data(bstr, data);
@@ -5418,7 +5248,7 @@
 VALUE 
 rb_bytestring_new() 
 {
-    VALUE bs = rb_bytestring_alloc(0, (SEL)"");
+    VALUE bs = rb_bytestring_alloc(0, 0);
     bs = (VALUE)objc_msgSend((id)bs, selInit); // [recv init];
     return bs;
 }
@@ -5465,12 +5295,18 @@
     return new;
 }
 
-long 
+inline long 
 rb_bytestring_length(VALUE str)
 {
     return CFDataGetLength(rb_bytestring_wrapped_data(str));
 }
 
+void
+rb_bytestring_resize(VALUE str, long newsize)
+{
+    CFDataSetLength(rb_bytestring_wrapped_data(str), newsize);
+}
+
 static CFIndex
 imp_rb_bytestring_length(void *rcv, SEL sel) 
 {
@@ -5488,20 +5324,43 @@
 imp_rb_bytestring_replaceCharactersInRange_withString(void *rcv, SEL sel,
 	CFRange range, void *str)
 {
-    const char *cstr = CFStringGetCStringPtr((CFStringRef)str,
-	    kCFStringEncodingUTF8);
-    assert(cstr != NULL); // TODO handle UTF-16 strings
-    const long length = CFStringGetLength((CFStringRef)str);
-
+    const UInt8 *bytes = (const UInt8 *)RSTRING_PTR(str);
+    const long length = RSTRING_LEN(str);
     CFMutableDataRef data = rb_bytestring_wrapped_data((VALUE)rcv);
 
-    // TODO: Have a more robust check than merely an assert(),
-    // and find out whether CFDataReplaceBytes complains if you give it
-    // a range outside the length of the wrapped data..
-    assert((length + range.location) < CFDataGetLength(data));
-    CFDataReplaceBytes(data, range, (const UInt8 *)cstr, length);
+    // No need to check if the given range fits in the data's bounds,
+    // CFDataReplaceBytes() will grow the object automatically for us.
+    CFDataReplaceBytes(data, range, bytes, length);
 }
 
+static void *
+imp_rb_bytestring_mutableCopy(void *rcv, SEL sel)
+{
+    VALUE new_bstr = rb_bytestring_new();
+    CFMutableDataRef rcv_data = rb_bytestring_wrapped_data((VALUE)rcv);
+    CFMutableDataRef new_data = rb_bytestring_wrapped_data(new_bstr);
+    CFDataAppendBytes(new_data, (const UInt8 *)CFDataGetMutableBytePtr(rcv_data),
+	    CFDataGetLength(rcv_data));
+    return (void *)new_bstr;
+}
+
+static void
+imp_rb_bytestring_cfAppendCString_length(void *rcv, SEL sel, const UInt8 *cstr,
+					 long len)
+{
+    CFDataAppendBytes(rb_bytestring_wrapped_data((VALUE)rcv), cstr, len);
+}
+
+static void
+imp_rb_bytestring_setString(void *rcv, SEL sel, void *new_str)
+{
+    CFMutableDataRef data = rb_bytestring_wrapped_data((VALUE)rcv);
+    CFRange data_range = CFRangeMake(0, CFDataGetLength(data));
+    const char *cstr = RSTRING_PTR(new_str);
+    const long len = RSTRING_LEN(new_str);
+    CFDataReplaceBytes(data, data_range, (const UInt8 *)cstr, len);
+} 
+
 /*
  *  A <code>String</code> object holds and manipulates an arbitrary sequence of
  *  bytes, typically representing characters. String objects may be created
@@ -5525,10 +5384,6 @@
     rb_const_set(rb_cObject, rb_intern("String"), rb_cNSMutableString);
     rb_set_class_path(rb_cNSMutableString, rb_cObject, "NSMutableString");
 
-    rb_objc_define_method(*(VALUE *)rb_cString, "__new_bytestring__",
-	    rb_str_new_bytestring_m, 1);
-    rb_objc_define_method(rb_cString, "__bytestring__?", rb_str_bytestring_m, 0);
-
     rb_include_module(rb_cString, rb_mComparable);
 
     rb_objc_define_method(*(VALUE *)rb_cString, "try_convert", rb_str_s_try_convert, 1);
@@ -5682,14 +5537,32 @@
     
     install_symbol_primitives();
 
-    rb_cByteString = (VALUE)objc_allocateClassPair((Class)objc_getClass("NSMutableString"), "ByteString", 0);
-    class_addIvar((Class)rb_cByteString, "wrappedData", sizeof(id), 0, "@");
-    rb_objc_install_method2((Class)rb_cByteString, "length", (IMP)imp_rb_bytestring_length);
-    rb_objc_install_method2((Class)rb_cByteString, "characterAtIndex:", (IMP)imp_rb_bytestring_characterAtIndex);
-    rb_objc_install_method2((Class)rb_cByteString, "replaceCharactersInRange:withString:", (IMP)imp_rb_bytestring_replaceCharactersInRange_withString);
+    rb_cByteString = (VALUE)objc_allocateClassPair((Class)rb_cNSMutableString,
+	    "ByteString", sizeof(void *));
+    RCLASS_SET_VERSION_FLAG(rb_cByteString, RCLASS_IS_STRING_SUBCLASS);
+    class_addIvar((Class)rb_cByteString, WRAPPED_DATA_IV_NAME, sizeof(id), 
+	    0, "@");
     objc_registerClassPair((Class)rb_cByteString);
-    rb_objc_define_method(rb_cByteString, "initialize", rb_bytestring_initialize, -1);
-    rb_objc_define_method(*(VALUE *)rb_cByteString, "alloc", rb_bytestring_alloc, 0);
 
-    wrappedDataOffset = ivar_getOffset(class_getInstanceVariable((Class)rb_cByteString, "wrappedData"));
+    rb_objc_install_method2((Class)rb_cByteString, "length",
+	    (IMP)imp_rb_bytestring_length);
+    rb_objc_install_method2((Class)rb_cByteString, "characterAtIndex:",
+	    (IMP)imp_rb_bytestring_characterAtIndex);
+    rb_objc_install_method2((Class)rb_cByteString,
+	    "replaceCharactersInRange:withString:",
+	    (IMP)imp_rb_bytestring_replaceCharactersInRange_withString);
+    rb_objc_install_method2((Class)rb_cByteString, "mutableCopy",
+	    (IMP)imp_rb_bytestring_mutableCopy);
+    rb_objc_install_method2((Class)rb_cByteString, "_cfAppendCString:length:",
+	    (IMP)imp_rb_bytestring_cfAppendCString_length);
+    rb_objc_install_method2((Class)rb_cByteString, "setString:",
+	    (IMP)imp_rb_bytestring_setString);
+    rb_objc_define_method(rb_cByteString, "initialize",
+	    rb_bytestring_initialize, -1);
+    rb_objc_define_method(*(VALUE *)rb_cByteString, "alloc",
+	    rb_bytestring_alloc, 0);
+
+    wrappedDataOffset = ivar_getOffset(
+	    class_getInstanceVariable((Class)rb_cByteString,
+		WRAPPED_DATA_IV_NAME));
 }

Modified: MacRuby/branches/experimental/time.c
===================================================================
--- MacRuby/branches/experimental/time.c	2009-03-16 01:14:55 UTC (rev 928)
+++ MacRuby/branches/experimental/time.c	2009-03-16 02:26:09 UTC (rev 929)
@@ -2241,8 +2241,10 @@
     rb_copy_generic_ivar(time, str);
 
     StringValue(str);
-    buf = (unsigned char *)RSTRING_BYTEPTR(str); /* ok */
-    if (RSTRING_BYTELEN(str) != 8) {
+    assert(*(VALUE *)str == rb_cByteString);
+
+    buf = (unsigned char *)rb_bytestring_byte_pointer(str);
+    if (rb_bytestring_length(str) != 8) {
 	rb_raise(rb_eTypeError, "marshaled time format differ");
     }
 
@@ -2280,7 +2282,7 @@
             long len;
             int digit;
             ptr = (unsigned char*)StringValuePtr(submicro);
-            len = RSTRING_BYTELEN(submicro);
+            len = RSTRING_LEN(submicro);
             if (0 < len) {
                 if (10 <= (digit = ptr[0] >> 4)) goto end_submicro;
                 nsec += digit * 100;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090315/b77aa48d/attachment-0001.html>


More information about the macruby-changes mailing list