[svn:parrot] r46336 - in trunk: src/pmc t/pmc

bacek at svn.parrot.org bacek at svn.parrot.org
Thu May 6 12:03:36 UTC 2010


Author: bacek
Date: Thu May  6 12:03:36 2010
New Revision: 46336
URL: https://trac.parrot.org/parrot/changeset/46336

Log:
Initial implementation of StringBuilder.push_string

Modified:
   trunk/src/pmc/stringbuilder.pmc
   trunk/t/pmc/stringbuilder.t

Modified: trunk/src/pmc/stringbuilder.pmc
==============================================================================
--- trunk/src/pmc/stringbuilder.pmc	Thu May  6 12:03:21 2010	(r46335)
+++ trunk/src/pmc/stringbuilder.pmc	Thu May  6 12:03:36 2010	(r46336)
@@ -20,6 +20,14 @@
 
 /* HEADERIZER HFILE: none */
 /* HEADERIZER BEGIN: static */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+
+static size_t calculate_capacity(SHIM_INTERP,
+    size_t current,
+    size_t additional);
+
+#define ASSERT_ARGS_calculate_capacity __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
 #define INITIAL_STRING_CAPACITY 128
@@ -96,6 +104,41 @@
         return Parrot_str_clone(INTERP, buffer);
     }
 
+/*
+
+=item C<STRING *push_string()>
+
+Append string to current buffer.
+
+=cut
+
+*/
+
+    VTABLE void push_string(STRING *s) {
+        STRING          *buffer;
+        size_t           total_size;
+
+        GET_ATTR_buffer(INTERP, SELF, buffer);
+
+        /* TODO If strings are incompatible - convert them */
+
+        /* Calculate (possibly new) total size */
+        total_size = calculate_capacity(INTERP, Buffer_buflen(buffer),
+                s->bufused);
+
+        /* Reallocate if necessary */
+        if (total_size > Buffer_buflen(buffer))
+            Parrot_gc_reallocate_string_storage(INTERP, buffer, total_size);
+
+        /* Tack s on the end of buffer */
+        mem_sys_memcopy((void *)((ptrcast_t)buffer->strstart + buffer->bufused),
+                s->strstart, s->bufused);
+
+        /* Update buffer */
+        buffer->bufused += s->bufused;
+        buffer->strlen  += Parrot_str_length(INTERP, s);
+    }
+
 
 /*
 
@@ -109,6 +152,46 @@
 
 
 /*
+
+=head2 Helper functions.
+
+=cut
+
+*/
+
+/*
+
+=item C<static size_t calculate_capacity(PARROT_INTERP, size_t current, size_t
+additional)>
+
+Calculate capacity for string. Usually StringBuilders used for "large"
+strings. So capacity rounded up by next algorithm:
+  - By 128 bytes if total capacity less then 1KB
+  - By 1KB if total less than 4KB
+  - By 4KB otherwise.
+
+This function is subject for tuning on real-world usage scenarios.
+
+=cut
+
+*/
+
+static size_t
+calculate_capacity(SHIM_INTERP, size_t current, size_t additional)
+{
+    ASSERT_ARGS(calculate_capacity)
+    size_t total_size = current + additional;
+    if (total_size < 1024)
+        total_size = (total_size + 128) & ~128;
+    else if (total_size < 4096)
+        total_size = (total_size + 1024) & ~1024;
+    else
+        total_size = (total_size + 4096) & ~4096;
+
+    return total_size;
+}
+
+/*
  * Local variables:
  *   c-file-style: "parrot"
  * End:

Modified: trunk/t/pmc/stringbuilder.t
==============================================================================
--- trunk/t/pmc/stringbuilder.t	Thu May  6 12:03:21 2010	(r46335)
+++ trunk/t/pmc/stringbuilder.t	Thu May  6 12:03:36 2010	(r46336)
@@ -20,8 +20,9 @@
 .sub 'main' :main
     .include 'test_more.pir'
 
-    plan(2)
+    plan(5)
     test_create()       # 2 tests
+    test_push_string()
 
     # END_OF_TESTS
 .end
@@ -39,6 +40,24 @@
 
 .end
 
+.sub 'test_push_string'
+    .local pmc sb
+    sb = new ['StringBuilder']
+
+    push sb, 'foo'
+    $S0 = sb
+    is( $S0, 'foo', 'First string pushed')
+
+    push sb, 'bar'
+    $S1 = sb
+    is( $S1, 'foobar', 'Second string pushed')
+
+    is( $S0, 'foo', '... without clobbering first string')
+
+    # Push large string which will cause reallocate
+
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100


More information about the parrot-commits mailing list