]> git.wincent.com - wikitext.git/commitdiff
Wrap str structs with Data_Wrap_Struct
authorWincent Colaiuta <win@wincent.com>
Sat, 23 Feb 2008 15:34:37 +0000 (16:34 +0100)
committerWincent Colaiuta <win@wincent.com>
Sat, 23 Feb 2008 15:34:37 +0000 (16:34 +0100)
This is the companion commit to 7f506d3 which wrapped ary structs. The
purpose of this commit is to ensure that str structs get freed in the
event of an abnormal exit from the parse function (ie. via an
exception).

Note that in order for this change to be made I had to change the
initialization of the tabulation struct; it needs to be initialized in
the parse function so that it can be added to the stack in the
appropriate scope, and this in turn means that it needs to be
pre-initialized rather than lazily initialized.

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

index dcb96a795fe60be2a2c1cef71b1b7b04d4b69f2d..6fd92eb4f416c01fd580b245bdb16b2f0f64b425 100644 (file)
@@ -207,9 +207,7 @@ inline void _Wikitext_indent(parser_t *parser)
     if (space_count > 0)
     {
         char *old_end, *new_end;
-        if (!parser->tabulation)
-            parser->tabulation = str_new_size(space_count);
-        else if (parser->tabulation->len < space_count)
+        if (parser->tabulation->len < space_count)
             str_grow(parser->tabulation, space_count); // reallocates if necessary
         old_end = parser->tabulation->ptr + parser->tabulation->len;
         new_end = parser->tabulation->ptr + space_count;
@@ -941,9 +939,11 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
     parser->space_to_underscore     = rb_iv_get(self, "@space_to_underscore");
     parser->special_link            = Qfalse;
     parser->line_ending             = str_new_from_string(line_ending);
+    GC_WRAP_STR(parser->line_ending, line_ending_gc);
     parser->base_indent             = base_indent;
     parser->current_indent          = 0;
-    parser->tabulation              = NULL;
+    parser->tabulation              = str_new();
+    GC_WRAP_STR(parser->tabulation, tabulation_gc);
 
     token_t _token;
     _token.type = NO_TOKEN;
@@ -2269,9 +2269,5 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
         token = NULL;
     } while (1);
 return_output:
-    // BUG: these will leak if we exit this function by raising an exception; need to investigate using Data_Wrap_Struct
-    str_free(parser->line_ending);
-    if (parser->tabulation)
-        str_free(parser->tabulation);
     return parser->output;
 }
index 7f0767691bcc8ed6a22139fa16f86f1e6d10d41b..fed1b83531ecdab591842527bee912ef70f03dd9 100644 (file)
--- a/ext/str.h
+++ b/ext/str.h
@@ -21,6 +21,10 @@ typedef struct
     long capacity;
 } str_t;
 
+// Mark the str struct designated by ptr as a participant in Ruby's mark-and-sweep garbage collection scheme.
+// A variable named name is placed on the C stack to prevent the structure from being prematurely collected.
+#define GC_WRAP_STR(ptr, name) volatile VALUE name = Data_Wrap_Struct(rb_cObject, 0, str_free, ptr)
+
 // create a new, empty string struct
 inline str_t *str_new(void)
 {