[macruby-changes] [157] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 18 23:22:34 PDT 2008


Revision: 157
          http://trac.macosforge.org/projects/ruby/changeset/157
Author:   lsansonetti at apple.com
Date:     2008-04-18 23:22:34 -0700 (Fri, 18 Apr 2008)

Log Message:
-----------
new string format implementation

Modified Paths:
--------------
    MacRuby/trunk/objc.m
    MacRuby/trunk/sprintf.c

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-04-19 06:21:34 UTC (rev 156)
+++ MacRuby/trunk/objc.m	2008-04-19 06:22:34 UTC (rev 157)
@@ -2532,6 +2532,139 @@
     assert(object_setInstanceVariable((id)obj, IVAR_CLUSTER_NAME, v) != NULL);
 }
 
+static void
+rb_objc_get_types_for_format_str(char **octypes, const int len, 
+				 const char *format_str)
+{
+    unsigned i, j, format_str_len;
+
+    format_str_len = strlen(format_str);
+    i = j = 0;
+
+    while (i < format_str_len) {
+	if (format_str[i++] != '%')
+	    continue;
+	if (i < format_str_len && format_str[i] == '%') {
+	    i++;
+	    continue;
+	}
+	while (i < format_str_len) {
+	    char *type = NULL;
+	    switch (format_str[i++]) {
+		case 'd':
+		case 'i':
+		case 'o':
+		case 'u':
+		case 'x':
+		case 'X':
+		case 'c':
+		case 'C':
+		    type = "i"; // _C_INT;
+		    break;
+
+		case 'D':
+		case 'O':
+		case 'U':
+		    type = "l"; // _C_LNG;
+		    break;
+
+		case 'f':       
+		case 'F':
+		case 'e':       
+		case 'E':
+		case 'g':       
+		case 'G':
+		case 'a':
+		case 'A':
+		    type = "d"; // _C_DBL;
+		    break;
+
+		case 's':
+		case 'S':
+		    type = "*"; // _C_CHARPTR;
+		    break;
+
+		case 'p':
+		    type = "^"; // _C_PTR;
+		    break;
+
+		case '@':
+		    type = "@"; // _C_ID;
+		    break;
+	    }
+
+	    if (type != NULL) {
+		if (len == 0 || j >= len)
+		    rb_raise(rb_eArgError, 
+			"Too much tokens in the format string `%s' "\
+			"for the given %d argument(s)", format_str, len);
+		octypes[j++] = type;
+		break;
+	    }
+	}
+    }
+    for (; j < len; j++)
+	octypes[j] = "@"; // _C_ID;
+}
+
+VALUE
+rb_str_format(int argc, const VALUE *argv, VALUE fmt)
+{
+    char **types;
+    ffi_type *ffi_rettype, **ffi_argtypes;
+    void *ffi_ret, **ffi_args;
+    ffi_cif *cif;
+    int i;
+    void *null;
+
+    if (argc == 0)
+	return fmt;
+
+    types = (char **)alloca(sizeof(char *) * argc);
+    ffi_argtypes = (ffi_type **)alloca(sizeof(ffi_type *) * argc + 4);
+    ffi_args = (void **)alloca(sizeof(void *) * argc + 4);
+
+    null = NULL;
+
+    ffi_argtypes[0] = &ffi_type_pointer;
+    ffi_args[0] = &null;
+    ffi_argtypes[1] = &ffi_type_pointer;
+    ffi_args[1] = &null;
+    ffi_argtypes[2] = &ffi_type_pointer;
+    ffi_args[2] = &fmt;
+   
+    if (argc > 0) {
+	rb_objc_get_types_for_format_str(types, argc, RSTRING_CPTR(fmt));
+  
+	for (i = 0; i < argc; i++) {
+	    ffi_argtypes[i + 3] = rb_objc_octype_to_ffitype(types[i]);
+	    ffi_args[i + 3] = (void *)alloca(ffi_argtypes[i + 3]->size);
+	    rb_objc_rval_to_ocval(argv[i], types[i], ffi_args[i + 3]);
+	}
+    }
+
+    ffi_argtypes[argc + 4] = NULL;
+    ffi_args[argc + 4] = NULL;
+
+    ffi_rettype = &ffi_type_pointer;
+    
+    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
+
+    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, argc + 3, ffi_rettype, ffi_argtypes)
+        != FFI_OK)
+        rb_fatal("can't prepare cif for CFStringCreateWithFormat");
+
+    ffi_ret = NULL;
+
+    ffi_call(cif, FFI_FN(CFStringCreateWithFormat), &ffi_ret, ffi_args);
+
+    if (ffi_ret != NULL) {
+        CFMakeCollectable((CFTypeRef)ffi_ret);
+        return (VALUE)ffi_ret;
+    }
+    return Qnil;
+}
+
 void
 Init_ObjC(void)
 {

Modified: MacRuby/trunk/sprintf.c
===================================================================
--- MacRuby/trunk/sprintf.c	2008-04-19 06:21:34 UTC (rev 156)
+++ MacRuby/trunk/sprintf.c	2008-04-19 06:22:34 UTC (rev 157)
@@ -243,6 +243,7 @@
     return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
 }
 
+#if !WITH_OBJC
 VALUE
 rb_str_format(int argc, const VALUE *argv, VALUE fmt)
 {
@@ -854,6 +855,7 @@
     if (tainted) OBJ_TAINT(result);
     return result;
 }
+#endif
 
 static void
 fmt_setup(char *buf, int c, int flags, int width, int prec)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080418/044b3c2c/attachment-0001.html


More information about the macruby-changes mailing list