[svn:parrot] r46540 - in branches/codestring: src/pmc t/pmc

bacek at svn.parrot.org bacek at svn.parrot.org
Wed May 12 21:24:41 UTC 2010


Author: bacek
Date: Wed May 12 21:24:40 2010
New Revision: 46540
URL: https://trac.parrot.org/parrot/changeset/46540

Log:
Add StringBuilder.append_format method (copyed from CodeString.emit method without adding newline

Modified:
   branches/codestring/src/pmc/stringbuilder.pmc
   branches/codestring/t/pmc/stringbuilder.t

Modified: branches/codestring/src/pmc/stringbuilder.pmc
==============================================================================
--- branches/codestring/src/pmc/stringbuilder.pmc	Wed May 12 21:02:57 2010	(r46539)
+++ branches/codestring/src/pmc/stringbuilder.pmc	Wed May 12 21:24:40 2010	(r46540)
@@ -282,6 +282,104 @@
                 Parrot_str_substr(INTERP, buffer, offset, length));
     }
 
+/*
+
+=item C<append_format(string fmt [, pmc args ] [, pmc hash ])>
+
+Add a line to a C<StringBuilder> object according to C<fmt>.
+The C<fmt> string can contain any number of "%-replacements"
+which are replaced by the corresponding values from C<args>
+or C<hash> prior to being appended to the string.  (Here
+C<args> is a slurpy array, and C<hash> is a slurpy hash.)
+
+The currently defined replacements include:
+
+    %0 %1 ... %9     the value from the args array at index 0..9
+    %,               the values of the args array separated by commas
+    %%               a percent sign
+
+A percent-sign followed by any other character that is a hash
+key receives the value of the hash element.
+
+=cut
+
+*/
+
+    METHOD append_format(STRING *fmt, PMC *args :slurpy, PMC *hash :slurpy :named) {
+        STRING * const percent     = CONST_STRING(INTERP, "%");
+        STRING * const comma       = CONST_STRING(INTERP, ",");
+        STRING * const comma_space = CONST_STRING(INTERP, ", ");
+        STRING * const newline     = CONST_STRING(INTERP, "\n");
+        STRING *key;
+        PMC    *stringbuilder = SELF;
+        INTVAL percentPos;
+        INTVAL pos = 0;
+
+        /* Loop over the format string, splitting it into chunks
+         * for the string builder. */
+        while (pos >= 0) {
+            /* Find the next % */
+            percentPos = Parrot_str_find_index(INTERP, fmt, percent, pos);
+
+            if (percentPos < 0) {
+                if (pos == 0) {
+                    VTABLE_push_string(INTERP, stringbuilder, fmt);
+                }
+                else {
+                    /* remaining string can be added as is. */
+                    VTABLE_push_string(INTERP, stringbuilder,
+                        Parrot_str_substr(INTERP, fmt, pos,
+                            Parrot_str_length(INTERP, fmt) -pos));
+                    }
+                break;
+            }
+            else {
+                /* slurp up to just before the % sign... */
+                VTABLE_push_string(INTERP, stringbuilder,
+                    Parrot_str_substr(INTERP, fmt, pos, percentPos - pos));
+                /* skip the % sign */
+                pos = percentPos + 1 ;
+            }
+
+            /* key is always a single character */
+            key = Parrot_str_substr(INTERP, fmt, pos++, 1);
+
+            if (VTABLE_exists_keyed_str(INTERP, hash, key)) {
+                VTABLE_push_string(INTERP, stringbuilder,
+                        VTABLE_get_string_keyed_str(INTERP, hash, key));
+            }
+            else if (Parrot_str_is_cclass(INTERP, enum_cclass_numeric, key, 0)) {
+                VTABLE_push_string(INTERP, stringbuilder,
+                    VTABLE_get_string_keyed_int(INTERP, args,
+                        Parrot_str_to_int(INTERP, key)));
+            }
+            else if (Parrot_str_equal(INTERP, key, comma)) {
+                INTVAL num_args = VTABLE_elements(INTERP, args);
+                INTVAL pos_args = 1;
+
+                VTABLE_push_string(INTERP, stringbuilder,
+                    VTABLE_get_string_keyed_int(INTERP, args, 0));
+
+                while (pos_args < num_args) {
+                    VTABLE_push_string(INTERP, stringbuilder, comma_space);
+                    VTABLE_push_string(INTERP, stringbuilder,
+                        VTABLE_get_string_keyed_int(INTERP, args, pos_args));
+                    pos_args++;
+                }
+            }
+            else if (Parrot_str_equal(INTERP, key, percent)) {
+                VTABLE_push_string(INTERP, stringbuilder, percent);
+            }
+            else {
+                /* %foo has no special meaning, pass it through unchanged */
+                VTABLE_push_string(INTERP, stringbuilder,
+                    Parrot_str_substr(INTERP, fmt, pos-2, 2));
+            }
+        }
+
+        RETURN(PMC *SELF);
+    }
+
 
 /*
 

Modified: branches/codestring/t/pmc/stringbuilder.t
==============================================================================
--- branches/codestring/t/pmc/stringbuilder.t	Wed May 12 21:02:57 2010	(r46539)
+++ branches/codestring/t/pmc/stringbuilder.t	Wed May 12 21:24:40 2010	(r46540)
@@ -20,7 +20,6 @@
 .sub 'main' :main
     .include 'test_more.pir'
 
-    plan(23)
     test_create()               # 2 tests
     test_push_string()          # 9 tests
     test_push_pmc()             # 4 tests
@@ -29,6 +28,13 @@
     test_set_string_native()    # 3 tests
     test_set_string_native_with_hash()    # 2 tests
 
+    emit_with_pos_args()
+    emit_with_percent_args()
+    emit_with_named_args()
+    emit_with_pos_and_named_args()
+
+    done_testing()
+
     # END_OF_TESTS
 .end
 
@@ -184,6 +190,61 @@
 
 .end
 
+.sub emit_with_pos_args
+    .local pmc code
+    code = new ["StringBuilder"]
+    code."append_format"("label_%0:\n",          1234)
+    code."append_format"("    say '%0, %1'\n",   "Hello", "World")
+    code."append_format"("    %0 = %2\n", "$I0", 24, 48)
+    is(code, <<'CODE', "code string with positional args looks fine")
+label_1234:
+    say 'Hello, World'
+    $I0 = 48
+CODE
+.end
+
+.sub emit_with_percent_args
+    .local pmc code
+    code = new ['StringBuilder']
+    code."append_format"("label_%0:\n",    1234)
+    code."append_format"("    say '%,'\n", "Hello")
+    code."append_format"("    say '%,'\n", "Hello", "World", "of", "Parrot")
+    code."append_format"("    say '%%0'\n")
+    is(code, <<'CODE', "code string with % args looks fine")
+label_1234:
+    say 'Hello'
+    say 'Hello, World, of, Parrot'
+    say '%0'
+CODE
+.end
+
+.sub emit_with_named_args
+    .local pmc code
+    code = new ['StringBuilder']
+    code."append_format"("label_%a:\n",         "a"=>1234)
+    code."append_format"("    say '%b, %c'\n",  "b"=>"Hello", "c"=>"World")
+    code."append_format"("    say '%d'\n",      "b"=>"Hello", "c"=>"World")
+    is(code, <<'CODE', "emit with named args looks fine")
+label_1234:
+    say 'Hello, World'
+    say '%d'
+CODE
+.end
+
+.sub emit_with_pos_and_named_args
+    .local pmc code
+    code = new ['StringBuilder']
+    code."append_format"("label_%a:\n", "a"=>1234)
+    code."append_format"("    %0 '%b, %c'\n", "say", "print", "b"=>"H", "c"=>"W")
+    code."append_format"("    say '%,, %c'\n", "alpha", "beta", "b"=>"H", "c"=>"W")
+    is(code, <<'CODE', "emit with pos + named args")
+label_1234:
+    say 'H, W'
+    say 'alpha, beta, W'
+CODE
+.end
+
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100


More information about the parrot-commits mailing list