Skip to content

Commit 3aedfe1

Browse files
committed
Extract arena helpers
1 parent eb59523 commit 3aedfe1

File tree

9 files changed

+214
-320
lines changed

9 files changed

+214
-320
lines changed

ext/herb/arena.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,43 @@ hb_arena_T* get_arena_from_value(VALUE arena_obj) {
136136
return wrapper->arena;
137137
}
138138

139+
VALUE get_arena_option_from_hash(VALUE options) {
140+
if (NIL_P(options)) return Qnil;
141+
142+
VALUE arena = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena"));
143+
if (NIL_P(arena)) { arena = rb_hash_lookup(options, ID2SYM(rb_intern("arena"))); }
144+
145+
return arena;
146+
}
147+
148+
bool setup_arena_context(VALUE external_arena, arena_context_T* context) {
149+
if (!NIL_P(external_arena)) {
150+
context->arena = get_arena_from_value(external_arena);
151+
context->owns_arena = false;
152+
return true;
153+
}
154+
155+
context->arena = malloc(sizeof(hb_arena_T));
156+
if (!context->arena) { return false; }
157+
158+
if (!hb_arena_init(context->arena, KB(512))) {
159+
free(context->arena);
160+
context->arena = NULL;
161+
return false;
162+
}
163+
164+
context->owns_arena = true;
165+
return true;
166+
}
167+
168+
void cleanup_arena_context(arena_context_T* context) {
169+
if (context->owns_arena && context->arena) {
170+
hb_arena_free(context->arena);
171+
free(context->arena);
172+
context->arena = NULL;
173+
}
174+
}
175+
139176
void Init_herb_arena(VALUE mHerb) {
140177
cArena = rb_define_class_under(mHerb, "Arena", rb_cObject);
141178
rb_define_alloc_func(cArena, Arena_allocate);

ext/herb/arena.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define HERB_EXT_ARENA_H
33

44
#include <ruby.h>
5+
#include <stdbool.h>
56
#include "../../src/include/util/hb_arena.h"
67

78
extern VALUE cArena;
@@ -16,6 +17,15 @@ VALUE Arena_stats(VALUE self);
1617

1718
hb_arena_T* get_arena_from_value(VALUE arena_obj);
1819

20+
typedef struct {
21+
hb_arena_T* arena;
22+
bool owns_arena;
23+
} arena_context_T;
24+
25+
VALUE get_arena_option_from_hash(VALUE options);
26+
bool setup_arena_context(VALUE external_arena, arena_context_T* context);
27+
void cleanup_arena_context(arena_context_T* context);
28+
1929
void Init_herb_arena(VALUE mHerb);
2030

2131
#endif

ext/herb/extension.c

Lines changed: 22 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -25,47 +25,26 @@ static VALUE Herb_lex(int argc, VALUE* argv, VALUE self) {
2525

2626
char* string = (char*) check_string(source);
2727
bool print_arena_stats = false;
28-
VALUE external_arena = Qnil;
2928

3029
if (!NIL_P(options)) {
3130
VALUE arena_stats = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena_stats"));
3231
if (NIL_P(arena_stats)) { arena_stats = rb_hash_lookup(options, ID2SYM(rb_intern("arena_stats"))); }
3332
if (!NIL_P(arena_stats) && RTEST(arena_stats)) { print_arena_stats = true; }
34-
35-
external_arena = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena"));
36-
if (NIL_P(external_arena)) { external_arena = rb_hash_lookup(options, ID2SYM(rb_intern("arena"))); }
3733
}
3834

39-
hb_arena_T* arena;
40-
bool owns_arena;
41-
42-
if (!NIL_P(external_arena)) {
43-
arena = get_arena_from_value(external_arena);
44-
owns_arena = false;
45-
} else {
46-
arena = malloc(sizeof(hb_arena_T));
47-
if (!arena) { return Qnil; }
48-
49-
if (!hb_arena_init(arena, KB(512))) {
50-
free(arena);
51-
return Qnil;
52-
}
53-
owns_arena = true;
54-
}
35+
arena_context_T context;
36+
if (!setup_arena_context(get_arena_option_from_hash(options), &context)) { return Qnil; }
5537

56-
herb_lex_result_T* lex_result = herb_lex(string, arena);
38+
herb_lex_result_T* lex_result = herb_lex(string, context.arena);
5739

5840
if (!lex_result) {
59-
if (owns_arena) {
60-
hb_arena_free(arena);
61-
free(arena);
62-
}
41+
cleanup_arena_context(&context);
6342
return Qnil;
6443
}
6544

6645
VALUE result = create_lex_result(lex_result->tokens, source);
6746

68-
if (print_arena_stats) { hb_arena_print_stats(arena); }
47+
if (print_arena_stats) { hb_arena_print_stats(context.arena); }
6948

7049
herb_free_lex_result(&lex_result);
7150

@@ -78,48 +57,27 @@ static VALUE Herb_lex_file(int argc, VALUE* argv, VALUE self) {
7857

7958
char* file_path = (char*) check_string(path);
8059
bool print_arena_stats = false;
81-
VALUE external_arena = Qnil;
8260

8361
if (!NIL_P(options)) {
8462
VALUE arena_stats = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena_stats"));
8563
if (NIL_P(arena_stats)) { arena_stats = rb_hash_lookup(options, ID2SYM(rb_intern("arena_stats"))); }
8664
if (!NIL_P(arena_stats) && RTEST(arena_stats)) { print_arena_stats = true; }
87-
88-
external_arena = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena"));
89-
if (NIL_P(external_arena)) { external_arena = rb_hash_lookup(options, ID2SYM(rb_intern("arena"))); }
9065
}
9166

92-
hb_arena_T* arena;
93-
bool owns_arena;
94-
95-
if (!NIL_P(external_arena)) {
96-
arena = get_arena_from_value(external_arena);
97-
owns_arena = false;
98-
} else {
99-
arena = malloc(sizeof(hb_arena_T));
100-
if (!arena) { return Qnil; }
101-
102-
if (!hb_arena_init(arena, KB(512))) {
103-
free(arena);
104-
return Qnil;
105-
}
106-
owns_arena = true;
107-
}
67+
arena_context_T context;
68+
if (!setup_arena_context(get_arena_option_from_hash(options), &context)) { return Qnil; }
10869

109-
herb_lex_result_T* lex_result = herb_lex_file(file_path, arena);
70+
herb_lex_result_T* lex_result = herb_lex_file(file_path, context.arena);
11071

11172
if (!lex_result) {
112-
if (owns_arena) {
113-
hb_arena_free(arena);
114-
free(arena);
115-
}
73+
cleanup_arena_context(&context);
11674
return Qnil;
11775
}
11876

11977
VALUE source_value = read_file_to_ruby_string(file_path);
12078
VALUE result = create_lex_result(lex_result->tokens, source_value);
12179

122-
if (print_arena_stats) { hb_arena_print_stats(arena); }
80+
if (print_arena_stats) { hb_arena_print_stats(context.arena); }
12381

12482
herb_free_lex_result(&lex_result);
12583

@@ -134,7 +92,6 @@ static VALUE Herb_parse(int argc, VALUE* argv, VALUE self) {
13492

13593
parser_options_T parser_options = HERB_DEFAULT_PARSER_OPTIONS;
13694
bool print_arena_stats = false;
137-
VALUE external_arena = Qnil;
13895

13996
if (!NIL_P(options)) {
14097
VALUE track_whitespace = rb_hash_lookup(options, rb_utf8_str_new_cstr("track_whitespace"));
@@ -152,43 +109,23 @@ static VALUE Herb_parse(int argc, VALUE* argv, VALUE self) {
152109
VALUE arena_stats = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena_stats"));
153110
if (NIL_P(arena_stats)) { arena_stats = rb_hash_lookup(options, ID2SYM(rb_intern("arena_stats"))); }
154111
if (!NIL_P(arena_stats) && RTEST(arena_stats)) { print_arena_stats = true; }
155-
156-
external_arena = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena"));
157-
if (NIL_P(external_arena)) { external_arena = rb_hash_lookup(options, ID2SYM(rb_intern("arena"))); }
158112
}
159113

160-
hb_arena_T* arena;
161-
bool owns_arena;
162-
163-
if (!NIL_P(external_arena)) {
164-
arena = get_arena_from_value(external_arena);
165-
owns_arena = false;
166-
} else {
167-
arena = malloc(sizeof(hb_arena_T));
168-
if (!arena) { return Qnil; }
169-
170-
if (!hb_arena_init(arena, KB(512))) {
171-
free(arena);
172-
return Qnil;
173-
}
174-
owns_arena = true;
175-
}
114+
arena_context_T context;
115+
if (!setup_arena_context(get_arena_option_from_hash(options), &context)) { return Qnil; }
176116

177-
AST_DOCUMENT_NODE_T* root = herb_parse(string, &parser_options, arena);
117+
AST_DOCUMENT_NODE_T* root = herb_parse(string, &parser_options, context.arena);
178118

179119
if (!root) {
180-
if (owns_arena) {
181-
hb_arena_free(arena);
182-
free(arena);
183-
}
120+
cleanup_arena_context(&context);
184121
return Qnil;
185122
}
186123

187-
root->owns_arena = owns_arena;
124+
root->owns_arena = context.owns_arena;
188125

189126
VALUE result = create_parse_result(root, source);
190127

191-
if (print_arena_stats) { hb_arena_print_stats(arena); }
128+
if (print_arena_stats) { hb_arena_print_stats(context.arena); }
192129

193130
ast_node_free((AST_NODE_T*) root);
194131

@@ -206,7 +143,6 @@ static VALUE Herb_parse_file(int argc, VALUE* argv, VALUE self) {
206143

207144
parser_options_T parser_options = HERB_DEFAULT_PARSER_OPTIONS;
208145
bool print_arena_stats = false;
209-
VALUE external_arena = Qnil;
210146

211147
if (!NIL_P(options)) {
212148
VALUE track_whitespace = rb_hash_lookup(options, rb_utf8_str_new_cstr("track_whitespace"));
@@ -224,43 +160,23 @@ static VALUE Herb_parse_file(int argc, VALUE* argv, VALUE self) {
224160
VALUE arena_stats = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena_stats"));
225161
if (NIL_P(arena_stats)) { arena_stats = rb_hash_lookup(options, ID2SYM(rb_intern("arena_stats"))); }
226162
if (!NIL_P(arena_stats) && RTEST(arena_stats)) { print_arena_stats = true; }
227-
228-
external_arena = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena"));
229-
if (NIL_P(external_arena)) { external_arena = rb_hash_lookup(options, ID2SYM(rb_intern("arena"))); }
230163
}
231164

232-
hb_arena_T* arena;
233-
bool owns_arena;
234-
235-
if (!NIL_P(external_arena)) {
236-
arena = get_arena_from_value(external_arena);
237-
owns_arena = false;
238-
} else {
239-
arena = malloc(sizeof(hb_arena_T));
240-
if (!arena) { return Qnil; }
241-
242-
if (!hb_arena_init(arena, KB(512))) {
243-
free(arena);
244-
return Qnil;
245-
}
246-
owns_arena = true;
247-
}
165+
arena_context_T context;
166+
if (!setup_arena_context(get_arena_option_from_hash(options), &context)) { return Qnil; }
248167

249-
AST_DOCUMENT_NODE_T* root = herb_parse(string, &parser_options, arena);
168+
AST_DOCUMENT_NODE_T* root = herb_parse(string, &parser_options, context.arena);
250169

251170
if (!root) {
252-
if (owns_arena) {
253-
hb_arena_free(arena);
254-
free(arena);
255-
}
171+
cleanup_arena_context(&context);
256172
return Qnil;
257173
}
258174

259-
root->owns_arena = owns_arena;
175+
root->owns_arena = context.owns_arena;
260176

261177
VALUE result = create_parse_result(root, source_value);
262178

263-
if (print_arena_stats) { hb_arena_print_stats(arena); }
179+
if (print_arena_stats) { hb_arena_print_stats(context.arena); }
264180

265181
ast_node_free((AST_NODE_T*) root);
266182

javascript/packages/node/extension/arena.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,50 @@ hb_arena_T* get_arena_from_value(napi_env env, napi_value arena_val) {
166166
return wrapper->arena;
167167
}
168168

169+
hb_arena_T* get_arena_option_from_object(napi_env env, napi_value options) {
170+
if (!options) return nullptr;
171+
172+
napi_valuetype valuetype;
173+
napi_typeof(env, options, &valuetype);
174+
if (valuetype != napi_object) return nullptr;
175+
176+
bool has_arena_prop;
177+
napi_has_named_property(env, options, "arena", &has_arena_prop);
178+
if (!has_arena_prop) return nullptr;
179+
180+
napi_value arena_prop;
181+
napi_get_named_property(env, options, "arena", &arena_prop);
182+
return get_arena_from_value(env, arena_prop);
183+
}
184+
185+
bool setup_arena_context(napi_env env, hb_arena_T* external_arena, arena_context_T* context) {
186+
if (external_arena) {
187+
context->arena = external_arena;
188+
context->owns_arena = false;
189+
return true;
190+
}
191+
192+
context->arena = (hb_arena_T*) malloc(sizeof(hb_arena_T));
193+
if (!context->arena) { return false; }
194+
195+
if (!hb_arena_init(context->arena, KB(512))) {
196+
free(context->arena);
197+
context->arena = nullptr;
198+
return false;
199+
}
200+
201+
context->owns_arena = true;
202+
return true;
203+
}
204+
205+
void cleanup_arena_context(arena_context_T* context) {
206+
if (context->owns_arena && context->arena) {
207+
hb_arena_free(context->arena);
208+
free(context->arena);
209+
context->arena = nullptr;
210+
}
211+
}
212+
169213
void Init_herb_arena(napi_env env, napi_value exports) {
170214
napi_property_descriptor arena_properties[] = {
171215
{ "reset", nullptr, Arena_reset, nullptr, nullptr, nullptr, napi_default, nullptr },

javascript/packages/node/extension/arena.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ napi_value Arena_free(napi_env env, napi_callback_info info);
1717

1818
hb_arena_T* get_arena_from_value(napi_env env, napi_value arena_val);
1919

20+
typedef struct {
21+
hb_arena_T* arena;
22+
bool owns_arena;
23+
} arena_context_T;
24+
25+
hb_arena_T* get_arena_option_from_object(napi_env env, napi_value options);
26+
bool setup_arena_context(napi_env env, hb_arena_T* external_arena, arena_context_T* context);
27+
void cleanup_arena_context(arena_context_T* context);
28+
2029
void Init_herb_arena(napi_env env, napi_value exports);
2130

2231
#endif

0 commit comments

Comments
 (0)