[svn:parrot] r46242 - branches/codestring/src/pmc

darbelo at svn.parrot.org darbelo at svn.parrot.org
Mon May 3 17:42:20 UTC 2010


Author: darbelo
Date: Mon May  3 17:42:20 2010
New Revision: 46242
URL: https://trac.parrot.org/parrot/changeset/46242

Log:
Merge codestring.pmc changes from trunk as a separate commit to ease review.

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

Modified: branches/codestring/src/pmc/codestring.pmc
==============================================================================
--- branches/codestring/src/pmc/codestring.pmc	Mon May  3 17:42:05 2010	(r46241)
+++ branches/codestring/src/pmc/codestring.pmc	Mon May  3 17:42:20 2010	(r46242)
@@ -39,7 +39,8 @@
 /* HEADERIZER END: static */
 
 pmclass CodeString extends String provides string auto_attrs {
-    ATTR PMC *linepos;            /* start of line positions */
+    ATTR PMC *linepos;  /* start of line positions */
+    ATTR PMC *strings;  /* array of strings... */
 
 /*
 
@@ -52,8 +53,8 @@
 */
 
     VTABLE void init() {
-        SUPER();
         SET_ATTR_linepos(INTERP, SELF, PMCNULL);
+        SET_ATTR_strings(INTERP, SELF, pmc_new(INTERP, enum_class_ResizableStringArray));
         PObj_custom_mark_SET(SELF);
     }
 
@@ -68,13 +69,19 @@
 */
 
     VTABLE void mark() {
-        SUPER();
         if (PMC_data(SELF)) {
-            PMC *linepos;
+            PMC *linepos, *strings;
 
-            GET_ATTR_linepos(INTERP, SELF, linepos);
+            /* force the join to avoid marking the RPA and lots of STRINGs */
+            STRING *contents = SELF.get_string();
+            UNUSED(contents);
 
+            GET_ATTR_linepos(INTERP, SELF, linepos);
             Parrot_gc_mark_PMC_alive(INTERP, linepos);
+
+            /* all that's in here now is a single STRING */
+            GET_ATTR_strings(INTERP, SELF, strings);
+            Parrot_gc_mark_PMC_alive(INTERP, strings);
         }
     }
 
@@ -97,7 +104,8 @@
 A percent-sign followed by any other character that is a hash
 key receives the value of the hash element.
 
-A newline is automatically added to the end of the fmt.
+A newline is automatically added to the end of the fmt, if one
+is not already present.
 
 =cut
 
@@ -108,60 +116,130 @@
     STRING * const comma       = CONST_STRING(INTERP, ",");
     STRING * const comma_space = CONST_STRING(INTERP, ", ");
     STRING * const newline     = CONST_STRING(INTERP, "\n");
-    PMC           *parts       = PMCNULL;
-    STRING *key, *repl, *S1;
-    INTVAL pos          = 0;
-    INTVAL replen       = 0;
+    STRING *key;
+    PMC    *strings;
+    INTVAL percentPos;
+    INTVAL pos = 0;
 
+    GET_ATTR_strings(INTERP, SELF, strings);
+
+    /* Loop over the format string, splitting it into chunks
+     * for the string builder. */
     while (pos >= 0) {
-        pos += replen;
-        pos = Parrot_str_find_index(INTERP, fmt, percent, pos);
-        if (pos < 0)
+        /* Find the next % */
+        percentPos = Parrot_str_find_index(INTERP, fmt, percent, pos);
+
+        if (percentPos < 0) {
+            if (pos == 0) {
+                VTABLE_push_string(INTERP, strings, fmt);
+            }
+            else {
+                /* remaining string can be added as is. */
+                VTABLE_push_string(INTERP, strings,
+                    Parrot_str_substr(INTERP, fmt, pos,
+                        Parrot_str_byte_length(INTERP, fmt) -pos));
+                }
             break;
+        }
+        else {
+            /* slurp up to just before the % sign... */
+            VTABLE_push_string(INTERP, strings,
+                Parrot_str_substr(INTERP, fmt, pos, percentPos - pos));
+            /* skip the % sign */
+            pos = percentPos + 1 ;
+        }
 
-        key = Parrot_str_substr(INTERP, fmt, pos+1, 1);
+        /* key is always a single character */
+        key = Parrot_str_substr(INTERP, fmt, pos++, 1);
 
         if (VTABLE_exists_keyed_str(INTERP, hash, key)) {
-            repl = VTABLE_get_string_keyed_str(INTERP, hash, key);
+            VTABLE_push_string(INTERP, strings,
+                    VTABLE_get_string_keyed_str(INTERP, hash, key));
         }
-        else if (Parrot_str_is_cclass(INTERP, enum_cclass_numeric, fmt, (UINTVAL)pos + 1)) {
-            const INTVAL I0 = Parrot_str_to_int(INTERP, key);
-            repl = VTABLE_get_string_keyed_int(INTERP, args, I0);
+        else if (Parrot_str_is_cclass(INTERP, enum_cclass_numeric, key, 0)) {
+            VTABLE_push_string(INTERP, strings,
+                VTABLE_get_string_keyed_int(INTERP, args,
+                    Parrot_str_to_int(INTERP, key)));
         }
         else if (Parrot_str_equal(INTERP, key, comma)) {
-            repl = Parrot_str_join(INTERP, comma_space, args);
+            INTVAL num_args = VTABLE_elements(INTERP, args);
+            INTVAL pos_args = 1;
+
+            VTABLE_push_string(INTERP, strings,
+                VTABLE_get_string_keyed_int(INTERP, args, 0));
+
+            while (pos_args < num_args) {
+                VTABLE_push_string(INTERP, strings, comma_space);
+                VTABLE_push_string(INTERP, strings,
+                    VTABLE_get_string_keyed_int(INTERP, args, pos_args));
+                pos_args++;
+            }
         }
         else if (Parrot_str_equal(INTERP, key, percent)) {
-            repl = percent;
+            VTABLE_push_string(INTERP, strings, percent);
         }
         else {
-            /* No substitution is necessary */
-            replen = 2;
-            continue;
+            /* %foo has no special meaning, pass it through unchanged */
+            VTABLE_push_string(INTERP, strings,
+                key = Parrot_str_substr(INTERP, fmt, pos-2, 2));
         }
+    }
+
+    /* Add a newline if necessary */
+    if ('\n' != Parrot_str_indexed(INTERP, fmt, Parrot_str_byte_length(INTERP, fmt) - 1))
+        VTABLE_push_string(INTERP, strings, newline);
+
+    RETURN(PMC *SELF);
+}
+
+/*
+
+=item get_string()
+
+Stringify ourselves.
+
+=cut
+
+*/
+
+
+    VTABLE STRING *get_string() {
+        PMC    *strings;
+
+        GET_ATTR_strings(INTERP, SELF, strings);
+
+        /* avoid unnecessary joins */
+        if (VTABLE_elements(INTERP, strings) <= 1)
+            return VTABLE_get_string_keyed_int(INTERP, strings, 0);
+        else {
+            STRING const *empty  = CONST_STRING(INTERP, "");
+            STRING const *result = Parrot_str_join(INTERP, empty, strings);
+
+            /* cache the result to avoid a join the next time. */
+            SELF.set_string_native(result);
 
-        fmt    = Parrot_str_replace(INTERP, fmt, pos, 2, repl);
-        replen = Parrot_str_byte_length(INTERP, repl);
+            return result;
+        }
     }
 
-    GET_ATTR_str_val(INTERP, SELF, S1);
+/*
 
-    parts = Parrot_pmc_new_temporary(INTERP, enum_class_ResizableStringArray);
-    VTABLE_set_integer_native(INTERP, parts, 3);
-    VTABLE_set_string_keyed_int(INTERP, parts, 0, S1);
-    VTABLE_set_string_keyed_int(INTERP, parts, 1, fmt);
+=item set_string_native()
 
-    /* Add a newline if necessary */
-    if ('\n' != Parrot_str_indexed(INTERP, fmt, Parrot_str_byte_length(INTERP, fmt) - 1))
-        VTABLE_set_string_keyed_int(INTERP, parts, 2, newline);
+Save our value as a single entry in the StringBuilder.
 
-    S1 = Parrot_str_join(INTERP, STRINGNULL, parts);
-    VTABLE_set_string_native(INTERP, SELF, S1);
-    Parrot_pmc_free_temporary(INTERP, parts);
+=cut
 
-    RETURN(PMC *SELF);
-  }
+*/
 
+    VTABLE void set_string_native(STRING *value) {
+        /* reuse our old stringBuilder */
+        PMC *strings;
+
+        GET_ATTR_strings(INTERP, SELF, strings);
+        VTABLE_set_integer_native(INTERP, strings, 0);
+        VTABLE_push_string(INTERP, strings, value);
+    }
 
 /*
 
@@ -189,13 +267,13 @@
 
         linepos = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
         /* get the string itself */
-        GET_ATTR_str_val(INTERP, SELF, str);
+        str = SELF.get_string();
         eos  = Parrot_str_byte_length(INTERP, str);
         /* find the first newline, if any */
         jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline,
                                       str, 0, eos);
         while (jpos < eos) {
-            jpos++;
+            ++jpos;
             /* add the start of line position */
             VTABLE_push_integer(INTERP, linepos, jpos);
 
@@ -203,7 +281,7 @@
             if (jpos < eos
             && string_ord(INTERP, str, jpos - 1)     == 13
             && string_ord(INTERP, str, jpos)         == 10) {
-                jpos++;
+                ++jpos;
             }
             /* search for the next newline */
             jpos = Parrot_str_find_cclass(INTERP, enum_cclass_newline,
@@ -220,7 +298,7 @@
     count = VTABLE_elements(INTERP, linepos);
     while (line < count
           && VTABLE_get_integer_keyed_int(INTERP, linepos, line) <= pos)
-        line++;
+        ++line;
 
     RETURN(INTVAL line);
   }
@@ -245,7 +323,7 @@
     STRING * const counter_as_string = Parrot_str_from_int(INTERP, counter);
     UNUSED(SELF);
 
-    counter++;
+    ++counter;
 
     if (!has_fmt) {
         RETURN(STRING *counter_as_string);
@@ -347,7 +425,7 @@
     STRING *       prefix        = NULL;
     STRING *       out           = open_bracket;
 
-    for (index = 0; index < elements; index++) {
+    for (index = 0; index < elements; ++index) {
         PMC * const P0 = VTABLE_get_pmc_keyed_int(INTERP, args, index);
 
         if (!PMC_IS_NULL(P0)) {
@@ -355,7 +433,7 @@
                 const INTVAL elements2 = VTABLE_elements(INTERP, P0);
                 INTVAL index2;
 
-                for (index2 = 0; index2 < elements2; index2++) {
+                for (index2 = 0; index2 < elements2; ++index2) {
                     STRING *S0   = VTABLE_get_string_keyed_int(INTERP, P0, index2);
                     (STRING *S0) = PCCINVOKE(INTERP, SELF, "escape", STRING *S0);
                     if (prefix)


More information about the parrot-commits mailing list