]> git.wincent.com - wikitext.git/commitdiff
Avoid copying string backing when returning from parse function
authorWincent Colaiuta <win@wincent.com>
Mon, 11 May 2009 19:00:20 +0000 (21:00 +0200)
committerWincent Colaiuta <win@wincent.com>
Mon, 11 May 2009 19:00:20 +0000 (21:00 +0200)
This is a somewhat nasty hack to avoid making a copy of the output
when it comes time to return from the function. For the time being
it will only work with Ruby 1.8.x, or at least, 1.9.x hasn't been
tested yet.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
ext/parser.c

index 399c2fe5e2129668bf824c9951ac57a94e712028..2dff381fff5fd76ffbf3f1b8e7250de9f474ad23 100644 (file)
@@ -56,6 +56,7 @@ typedef struct
     bool    space_to_underscore;
 } parser_t;
 
+const char null_str[]                   = { 0 };
 const char escaped_no_wiki_start[]      = "&lt;nowiki&gt;";
 const char escaped_no_wiki_end[]        = "&lt;/nowiki&gt;";
 const char literal_strong_em[]          = "'''''";
@@ -1080,6 +1081,9 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
     long len = RSTRING_LEN(string);
     char *pe = p + len;
 
+    // the eventual return value
+    VALUE out = rb_str_new2("");
+
     // access these once per parse
     VALUE line_ending   = rb_iv_get(self, "@line_ending");
     line_ending         = StringValue(line_ending);
@@ -2579,6 +2583,13 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
         token = NULL;
     } while (1);
 return_output:
-    // TODO: make this fast
-    return string_from_str(parser->output);
+    // nasty hack to avoid re-allocating our return value
+    str_append(parser->output, null_str, 1); // null-terminate
+
+    // won't work for Ruby 1.9
+    free(RSTRING(out)->ptr);
+    RSTRING(out)->ptr = parser->output->ptr;
+    RSTRING(out)->len = parser->output->len - 1; // don't count null termination
+    parser->output->ptr = NULL; // don't double-free
+    return out;
 }