@@ -14,28 +14,77 @@ VALUE cResult;
1414VALUE cLexResult ;
1515VALUE cParseResult ;
1616
17- static VALUE Herb_lex (VALUE self , VALUE source ) {
18- char * string = (char * ) check_string (source );
17+ typedef struct {
18+ AST_DOCUMENT_NODE_T * root ;
19+ VALUE source ;
20+ } parse_args_T ;
21+
22+ typedef struct {
23+ hb_array_T * tokens ;
24+ VALUE source ;
25+ } lex_args_T ;
26+
27+ typedef struct {
28+ char * buffer_value ;
29+ } buffer_args_T ;
30+
31+ static VALUE parse_convert_body (VALUE arg ) {
32+ parse_args_T * args = (parse_args_T * ) arg ;
33+
34+ return create_parse_result (args -> root , args -> source );
35+ }
36+
37+ static VALUE parse_cleanup (VALUE arg ) {
38+ parse_args_T * args = (parse_args_T * ) arg ;
39+
40+ if (args -> root != NULL ) { ast_node_free ((AST_NODE_T * ) args -> root ); }
41+
42+ return Qnil ;
43+ }
44+
45+ static VALUE lex_convert_body (VALUE arg ) {
46+ lex_args_T * args = (lex_args_T * ) arg ;
47+
48+ return create_lex_result (args -> tokens , args -> source );
49+ }
50+
51+ static VALUE lex_cleanup (VALUE arg ) {
52+ lex_args_T * args = (lex_args_T * ) arg ;
53+
54+ if (args -> tokens != NULL ) { herb_free_tokens (& args -> tokens ); }
1955
20- hb_array_T * tokens = herb_lex (string );
56+ return Qnil ;
57+ }
58+
59+ static VALUE buffer_to_string_body (VALUE arg ) {
60+ buffer_args_T * args = (buffer_args_T * ) arg ;
61+
62+ return rb_utf8_str_new_cstr (args -> buffer_value );
63+ }
64+
65+ static VALUE buffer_cleanup (VALUE arg ) {
66+ buffer_args_T * args = (buffer_args_T * ) arg ;
67+
68+ if (args -> buffer_value != NULL ) { free (args -> buffer_value ); }
69+
70+ return Qnil ;
71+ }
2172
22- VALUE result = create_lex_result (tokens , source );
73+ static VALUE Herb_lex (VALUE self , VALUE source ) {
74+ char * string = (char * ) check_string (source );
2375
24- herb_free_tokens ( & tokens ) ;
76+ lex_args_T args = { . tokens = herb_lex ( string ), . source = source } ;
2577
26- return result ;
78+ return rb_ensure ( lex_convert_body , ( VALUE ) & args , lex_cleanup , ( VALUE ) & args ) ;
2779}
2880
2981static VALUE Herb_lex_file (VALUE self , VALUE path ) {
3082 char * file_path = (char * ) check_string (path );
31- hb_array_T * tokens = herb_lex_file (file_path );
3283
3384 VALUE source_value = read_file_to_ruby_string (file_path );
34- VALUE result = create_lex_result ( tokens , source_value ) ;
85+ lex_args_T args = { . tokens = herb_lex_file ( file_path ), . source = source_value } ;
3586
36- herb_free_tokens (& tokens );
37-
38- return result ;
87+ return rb_ensure (lex_convert_body , (VALUE ) & args , lex_cleanup , (VALUE ) & args );
3988}
4089
4190static VALUE Herb_parse (int argc , VALUE * argv , VALUE self ) {
@@ -60,13 +109,9 @@ static VALUE Herb_parse(int argc, VALUE* argv, VALUE self) {
60109 if (!NIL_P (strict )) { parser_options .strict = RTEST (strict ); }
61110 }
62111
63- AST_DOCUMENT_NODE_T * root = herb_parse (string , & parser_options );
64-
65- VALUE result = create_parse_result (root , source );
112+ parse_args_T args = { .root = herb_parse (string , & parser_options ), .source = source };
66113
67- ast_node_free ((AST_NODE_T * ) root );
68-
69- return result ;
114+ return rb_ensure (parse_convert_body , (VALUE ) & args , parse_cleanup , (VALUE ) & args );
70115}
71116
72117static VALUE Herb_parse_file (int argc , VALUE * argv , VALUE self ) {
@@ -94,13 +139,9 @@ static VALUE Herb_parse_file(int argc, VALUE* argv, VALUE self) {
94139 if (!NIL_P (strict )) { parser_options .strict = RTEST (strict ); }
95140 }
96141
97- AST_DOCUMENT_NODE_T * root = herb_parse (string , & parser_options );
98-
99- VALUE result = create_parse_result (root , source_value );
142+ parse_args_T args = { .root = herb_parse (string , & parser_options ), .source = source_value };
100143
101- ast_node_free ((AST_NODE_T * ) root );
102-
103- return result ;
144+ return rb_ensure (parse_convert_body , (VALUE ) & args , parse_cleanup , (VALUE ) & args );
104145}
105146
106147static VALUE Herb_extract_ruby (int argc , VALUE * argv , VALUE self ) {
@@ -132,10 +173,9 @@ static VALUE Herb_extract_ruby(int argc, VALUE* argv, VALUE self) {
132173
133174 herb_extract_ruby_to_buffer_with_options (string , & output , & extract_options );
134175
135- VALUE result = rb_utf8_str_new_cstr (output .value );
136- free (output .value );
176+ buffer_args_T args = { .buffer_value = output .value };
137177
138- return result ;
178+ return rb_ensure ( buffer_to_string_body , ( VALUE ) & args , buffer_cleanup , ( VALUE ) & args ) ;
139179}
140180
141181static VALUE Herb_extract_html (VALUE self , VALUE source ) {
@@ -146,10 +186,9 @@ static VALUE Herb_extract_html(VALUE self, VALUE source) {
146186
147187 herb_extract_html_to_buffer (string , & output );
148188
149- VALUE result = rb_utf8_str_new_cstr (output .value );
150- free (output .value );
189+ buffer_args_T args = { .buffer_value = output .value };
151190
152- return result ;
191+ return rb_ensure ( buffer_to_string_body , ( VALUE ) & args , buffer_cleanup , ( VALUE ) & args ) ;
153192}
154193
155194static VALUE Herb_version (VALUE self ) {
@@ -171,6 +210,9 @@ __attribute__((__visibility__("default"))) void Init_herb(void) {
171210 cLexResult = rb_define_class_under (mHerb , "LexResult" , cResult );
172211 cParseResult = rb_define_class_under (mHerb , "ParseResult" , cResult );
173212
213+ rb_init_node_classes ();
214+ rb_init_error_classes ();
215+
174216 rb_define_singleton_method (mHerb , "parse" , Herb_parse , -1 );
175217 rb_define_singleton_method (mHerb , "lex" , Herb_lex , 1 );
176218 rb_define_singleton_method (mHerb , "parse_file" , Herb_parse_file , -1 );
0 commit comments