[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