ox 2.14.6 → 2.14.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/ext/ox/builder.c +0 -4
- data/ext/ox/cache.c +309 -131
- data/ext/ox/cache.h +10 -10
- data/ext/ox/dump.c +2 -2
- data/ext/ox/extconf.rb +4 -2
- data/ext/ox/gen_load.c +5 -73
- data/ext/ox/hash_load.c +0 -4
- data/ext/ox/intern.c +153 -0
- data/ext/ox/intern.h +25 -0
- data/ext/ox/obj_load.c +14 -86
- data/ext/ox/ox.c +1015 -935
- data/ext/ox/ox.h +186 -210
- data/ext/ox/parse.c +72 -31
- data/ext/ox/sax.c +1100 -1276
- data/ext/ox/sax.h +45 -31
- data/ext/ox/sax_as.c +3 -5
- data/ext/ox/sax_buf.c +7 -16
- data/ext/ox/slotcache.c +158 -0
- data/ext/ox/slotcache.h +19 -0
- data/lib/ox/version.rb +1 -1
- metadata +7 -4
- data/ext/ox/sax_has.h +0 -53
data/ext/ox/gen_load.c
CHANGED
@@ -10,10 +10,9 @@
|
|
10
10
|
#include <stdarg.h>
|
11
11
|
|
12
12
|
#include "ruby.h"
|
13
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
14
13
|
#include "ruby/encoding.h"
|
15
|
-
#endif
|
16
14
|
#include "ox.h"
|
15
|
+
#include "intern.h"
|
17
16
|
|
18
17
|
static void instruct(PInfo pi, const char *target, Attr attrs, const char *content);
|
19
18
|
static void create_doc(PInfo pi);
|
@@ -103,7 +102,6 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
|
|
103
102
|
sym = rb_funcall(pi->options->attr_key_mod, ox_call_id, 1, rb_str_new2(attrs->name));
|
104
103
|
rb_hash_aset(ah, sym, rb_str_new2(attrs->value));
|
105
104
|
} else if (Yes == pi->options->sym_keys) {
|
106
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
107
105
|
if (0 != pi->options->rb_enc) {
|
108
106
|
VALUE rstr = rb_str_new2(attrs->name);
|
109
107
|
|
@@ -113,17 +111,14 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
|
|
113
111
|
sym = ID2SYM(rb_intern(attrs->name));
|
114
112
|
}
|
115
113
|
sym = ID2SYM(rb_intern(attrs->name));
|
116
|
-
#endif
|
117
114
|
rb_hash_aset(ah, sym, rb_str_new2(attrs->value));
|
118
115
|
} else {
|
119
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
120
116
|
volatile VALUE rstr = rb_str_new2(attrs->name);
|
121
117
|
|
122
118
|
if (0 != pi->options->rb_enc) {
|
123
119
|
rb_enc_associate(rstr, pi->options->rb_enc);
|
124
120
|
}
|
125
121
|
rb_hash_aset(ah, rstr, rb_str_new2(attrs->value));
|
126
|
-
#endif
|
127
122
|
}
|
128
123
|
if (0 == strcmp("encoding", attrs->name)) {
|
129
124
|
pi->options->rb_enc = rb_enc_find(attrs->value);
|
@@ -195,11 +190,9 @@ add_doctype(PInfo pi, const char *docType) {
|
|
195
190
|
VALUE n = rb_obj_alloc(ox_doctype_clas);
|
196
191
|
VALUE s = rb_str_new2(docType);
|
197
192
|
|
198
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
199
193
|
if (0 != pi->options->rb_enc) {
|
200
194
|
rb_enc_associate(s, pi->options->rb_enc);
|
201
195
|
}
|
202
|
-
#endif
|
203
196
|
rb_ivar_set(n, ox_at_value_id, s);
|
204
197
|
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
205
198
|
create_doc(pi);
|
@@ -212,11 +205,9 @@ add_comment(PInfo pi, const char *comment) {
|
|
212
205
|
VALUE n = rb_obj_alloc(ox_comment_clas);
|
213
206
|
VALUE s = rb_str_new2(comment);
|
214
207
|
|
215
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
216
208
|
if (0 != pi->options->rb_enc) {
|
217
209
|
rb_enc_associate(s, pi->options->rb_enc);
|
218
210
|
}
|
219
|
-
#endif
|
220
211
|
rb_ivar_set(n, ox_at_value_id, s);
|
221
212
|
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
222
213
|
create_doc(pi);
|
@@ -229,11 +220,9 @@ add_cdata(PInfo pi, const char *cdata, size_t len) {
|
|
229
220
|
VALUE n = rb_obj_alloc(ox_cdata_clas);
|
230
221
|
VALUE s = rb_str_new2(cdata);
|
231
222
|
|
232
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
233
223
|
if (0 != pi->options->rb_enc) {
|
234
224
|
rb_enc_associate(s, pi->options->rb_enc);
|
235
225
|
}
|
236
|
-
#endif
|
237
226
|
rb_ivar_set(n, ox_at_value_id, s);
|
238
227
|
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
239
228
|
create_doc(pi);
|
@@ -245,11 +234,9 @@ static void
|
|
245
234
|
add_text(PInfo pi, char *text, int closed) {
|
246
235
|
VALUE s = rb_str_new2(text);
|
247
236
|
|
248
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
249
237
|
if (0 != pi->options->rb_enc) {
|
250
238
|
rb_enc_associate(s, pi->options->rb_enc);
|
251
239
|
}
|
252
|
-
#endif
|
253
240
|
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
254
241
|
create_doc(pi);
|
255
242
|
}
|
@@ -264,11 +251,9 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
264
251
|
if (Qnil != pi->options->element_key_mod) {
|
265
252
|
s = rb_funcall(pi->options->element_key_mod, ox_call_id, 1, s);
|
266
253
|
}
|
267
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
268
254
|
if (0 != pi->options->rb_enc) {
|
269
255
|
rb_enc_associate(s, pi->options->rb_enc);
|
270
256
|
}
|
271
|
-
#endif
|
272
257
|
e = rb_obj_alloc(ox_element_clas);
|
273
258
|
rb_ivar_set(e, ox_at_value_id, s);
|
274
259
|
if (0 != attrs->name) {
|
@@ -280,40 +265,14 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
280
265
|
if (Qnil != pi->options->attr_key_mod) {
|
281
266
|
sym = rb_funcall(pi->options->attr_key_mod, ox_call_id, 1, rb_str_new2(attrs->name));
|
282
267
|
} else if (Yes == pi->options->sym_keys) {
|
283
|
-
|
284
|
-
|
285
|
-
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, attrs->name, &slot, 0))) {
|
286
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
287
|
-
if (0 != pi->options->rb_enc) {
|
288
|
-
VALUE rstr = rb_str_new2(attrs->name);
|
289
|
-
|
290
|
-
rb_enc_associate(rstr, pi->options->rb_enc);
|
291
|
-
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
292
|
-
} else {
|
293
|
-
sym = ID2SYM(rb_intern(attrs->name));
|
294
|
-
}
|
295
|
-
#else
|
296
|
-
sym = ID2SYM(rb_intern(attrs->name));
|
297
|
-
#endif
|
298
|
-
// Needed for Ruby 2.2 to get around the GC of symbols
|
299
|
-
// created with to_sym which is needed for encoded symbols.
|
300
|
-
rb_ary_push(ox_sym_bank, sym);
|
301
|
-
*slot = sym;
|
302
|
-
}
|
268
|
+
sym = ox_sym_intern(attrs->name, strlen(attrs->name), NULL);
|
303
269
|
} else {
|
304
|
-
sym =
|
305
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
306
|
-
if (0 != pi->options->rb_enc) {
|
307
|
-
rb_enc_associate(sym, pi->options->rb_enc);
|
308
|
-
}
|
309
|
-
#endif
|
270
|
+
sym = ox_str_intern(attrs->name, strlen(attrs->name), NULL);
|
310
271
|
}
|
311
272
|
s = rb_str_new2(attrs->value);
|
312
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
313
273
|
if (0 != pi->options->rb_enc) {
|
314
274
|
rb_enc_associate(s, pi->options->rb_enc);
|
315
275
|
}
|
316
|
-
#endif
|
317
276
|
rb_hash_aset(ah, sym, s);
|
318
277
|
}
|
319
278
|
rb_ivar_set(e, ox_attributes_id, ah);
|
@@ -349,14 +308,12 @@ add_instruct(PInfo pi, const char *name, Attr attrs, const char *content) {
|
|
349
308
|
if (0 != content) {
|
350
309
|
c = rb_str_new2(content);
|
351
310
|
}
|
352
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
353
311
|
if (0 != pi->options->rb_enc) {
|
354
312
|
rb_enc_associate(s, pi->options->rb_enc);
|
355
313
|
if (0 != content) {
|
356
314
|
rb_enc_associate(c, pi->options->rb_enc);
|
357
315
|
}
|
358
316
|
}
|
359
|
-
#endif
|
360
317
|
inst = rb_obj_alloc(ox_instruct_clas);
|
361
318
|
rb_ivar_set(inst, ox_at_value_id, s);
|
362
319
|
if (0 != content) {
|
@@ -366,43 +323,18 @@ add_instruct(PInfo pi, const char *name, Attr attrs, const char *content) {
|
|
366
323
|
|
367
324
|
for (; 0 != attrs->name; attrs++) {
|
368
325
|
volatile VALUE sym;
|
369
|
-
VALUE *slot;
|
370
326
|
|
371
327
|
if (Qnil != pi->options->attr_key_mod) {
|
372
328
|
sym = rb_funcall(pi->options->attr_key_mod, ox_call_id, 1, rb_str_new2(attrs->name));
|
373
329
|
} else if (Yes == pi->options->sym_keys) {
|
374
|
-
|
375
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
376
|
-
if (0 != pi->options->rb_enc) {
|
377
|
-
VALUE rstr = rb_str_new2(attrs->name);
|
378
|
-
|
379
|
-
rb_enc_associate(rstr, pi->options->rb_enc);
|
380
|
-
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
381
|
-
} else {
|
382
|
-
sym = ID2SYM(rb_intern(attrs->name));
|
383
|
-
}
|
384
|
-
#else
|
385
|
-
sym = ID2SYM(rb_intern(attrs->name));
|
386
|
-
#endif
|
387
|
-
// Needed for Ruby 2.2 to get around the GC of symbols
|
388
|
-
// created with to_sym which is needed for encoded symbols.
|
389
|
-
rb_ary_push(ox_sym_bank, sym);
|
390
|
-
*slot = sym;
|
391
|
-
}
|
330
|
+
sym = ox_sym_intern(attrs->name, strlen(attrs->name), NULL);
|
392
331
|
} else {
|
393
|
-
sym =
|
394
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
395
|
-
if (0 != pi->options->rb_enc) {
|
396
|
-
rb_enc_associate(sym, pi->options->rb_enc);
|
397
|
-
}
|
398
|
-
#endif
|
332
|
+
sym = ox_str_intern(attrs->name, strlen(attrs->name), NULL);
|
399
333
|
}
|
400
334
|
s = rb_str_new2(attrs->value);
|
401
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
402
335
|
if (0 != pi->options->rb_enc) {
|
403
336
|
rb_enc_associate(s, pi->options->rb_enc);
|
404
337
|
}
|
405
|
-
#endif
|
406
338
|
rb_hash_aset(ah, sym, s);
|
407
339
|
}
|
408
340
|
rb_ivar_set(inst, ox_attributes_id, ah);
|
data/ext/ox/hash_load.c
CHANGED
@@ -78,11 +78,9 @@ add_str(PInfo pi, VALUE s) {
|
|
78
78
|
Helper parent = helper_stack_peek(&pi->helpers);
|
79
79
|
volatile VALUE a;
|
80
80
|
|
81
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
82
81
|
if (0 != pi->options->rb_enc) {
|
83
82
|
rb_enc_associate(s, pi->options->rb_enc);
|
84
83
|
}
|
85
|
-
#endif
|
86
84
|
switch (parent->type) {
|
87
85
|
case NoCode:
|
88
86
|
parent->obj = s;
|
@@ -131,11 +129,9 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
131
129
|
key = rb_str_new2(attrs->name);
|
132
130
|
}
|
133
131
|
val = rb_str_new2(attrs->value);
|
134
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
135
132
|
if (0 != pi->options->rb_enc) {
|
136
133
|
rb_enc_associate(val, pi->options->rb_enc);
|
137
134
|
}
|
138
|
-
#endif
|
139
135
|
rb_hash_aset(h, key, val);
|
140
136
|
}
|
141
137
|
a = rb_ary_new();
|
data/ext/ox/intern.c
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
// Copyright (c) 2011, 2021 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
|
+
|
4
|
+
#include "intern.h"
|
5
|
+
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
#include "cache.h"
|
9
|
+
#include "ox.h"
|
10
|
+
|
11
|
+
// These are statics but in an attempt to stop the cross linking or maybe
|
12
|
+
// something in Ruby they all have been given an ox prefix.
|
13
|
+
static struct _cache *ox_str_cache = NULL;
|
14
|
+
static VALUE ox_str_cache_obj;
|
15
|
+
|
16
|
+
static struct _cache *ox_sym_cache = NULL;
|
17
|
+
static VALUE ox_sym_cache_obj;
|
18
|
+
|
19
|
+
static struct _cache *ox_attr_cache = NULL;
|
20
|
+
static VALUE ox_attr_cache_obj;
|
21
|
+
|
22
|
+
static struct _cache *ox_id_cache = NULL;
|
23
|
+
static VALUE ox_id_cache_obj;
|
24
|
+
|
25
|
+
static VALUE form_str(const char *str, size_t len) {
|
26
|
+
return rb_str_freeze(rb_utf8_str_new(str, len));
|
27
|
+
}
|
28
|
+
|
29
|
+
static VALUE form_sym(const char *str, size_t len) {
|
30
|
+
return rb_to_symbol(rb_str_freeze(rb_utf8_str_new(str, len)));
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE form_attr(const char *str, size_t len) {
|
34
|
+
char buf[256];
|
35
|
+
|
36
|
+
if (sizeof(buf) - 2 <= len) {
|
37
|
+
char *b = ALLOC_N(char, len + 2);
|
38
|
+
ID id;
|
39
|
+
|
40
|
+
if ('~' == *str) {
|
41
|
+
memcpy(b, str + 1, len - 1);
|
42
|
+
b[len - 1] = '\0';
|
43
|
+
len -= 2;
|
44
|
+
} else {
|
45
|
+
*b = '@';
|
46
|
+
memcpy(b + 1, str, len);
|
47
|
+
b[len + 1] = '\0';
|
48
|
+
}
|
49
|
+
id = rb_intern3(buf, len + 1, rb_utf8_encoding());
|
50
|
+
xfree(b);
|
51
|
+
return id;
|
52
|
+
}
|
53
|
+
if ('~' == *str) {
|
54
|
+
memcpy(buf, str + 1, len - 1);
|
55
|
+
buf[len - 1] = '\0';
|
56
|
+
len -= 2;
|
57
|
+
} else {
|
58
|
+
*buf = '@';
|
59
|
+
memcpy(buf + 1, str, len);
|
60
|
+
buf[len + 1] = '\0';
|
61
|
+
}
|
62
|
+
return (VALUE)rb_intern3(buf, len + 1, rb_utf8_encoding());
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE form_id(const char *str, size_t len) {
|
66
|
+
return (VALUE)rb_intern3(str, len, rb_utf8_encoding());
|
67
|
+
}
|
68
|
+
|
69
|
+
void ox_hash_init() {
|
70
|
+
VALUE cache_class = rb_define_class_under(Ox, "Cache", rb_cObject);
|
71
|
+
|
72
|
+
ox_str_cache = ox_cache_create(0, form_str, true, false);
|
73
|
+
ox_str_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_str_cache);
|
74
|
+
rb_gc_register_address(&ox_str_cache_obj);
|
75
|
+
|
76
|
+
ox_sym_cache = ox_cache_create(0, form_sym, true, false);
|
77
|
+
ox_sym_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_sym_cache);
|
78
|
+
rb_gc_register_address(&ox_sym_cache_obj);
|
79
|
+
|
80
|
+
ox_attr_cache = ox_cache_create(0, form_attr, false, false);
|
81
|
+
ox_attr_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_attr_cache);
|
82
|
+
rb_gc_register_address(&ox_attr_cache_obj);
|
83
|
+
|
84
|
+
ox_id_cache = ox_cache_create(0, form_id, false, false);
|
85
|
+
ox_id_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_id_cache);
|
86
|
+
rb_gc_register_address(&ox_id_cache_obj);
|
87
|
+
}
|
88
|
+
|
89
|
+
VALUE
|
90
|
+
ox_str_intern(const char *key, size_t len, const char **keyp) {
|
91
|
+
// For huge cache sizes over half a million the rb_enc_interned_str
|
92
|
+
// performs slightly better but at more "normal" size of a several
|
93
|
+
// thousands the cache intern performs about 20% better.
|
94
|
+
#if HAVE_RB_ENC_INTERNED_STR && 0
|
95
|
+
return rb_enc_interned_str(key, len, rb_utf8_encoding());
|
96
|
+
#else
|
97
|
+
return ox_cache_intern(ox_str_cache, key, len, keyp);
|
98
|
+
#endif
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE
|
102
|
+
ox_sym_intern(const char *key, size_t len, const char **keyp) {
|
103
|
+
return ox_cache_intern(ox_sym_cache, key, len, keyp);
|
104
|
+
}
|
105
|
+
|
106
|
+
ID ox_attr_intern(const char *key, size_t len) {
|
107
|
+
return ox_cache_intern(ox_attr_cache, key, len, NULL);
|
108
|
+
}
|
109
|
+
|
110
|
+
ID ox_id_intern(const char *key, size_t len) {
|
111
|
+
return ox_cache_intern(ox_id_cache, key, len, NULL);
|
112
|
+
}
|
113
|
+
|
114
|
+
char *ox_strndup(const char *s, size_t len) {
|
115
|
+
char *d = ALLOC_N(char, len + 1);
|
116
|
+
|
117
|
+
memcpy(d, s, len);
|
118
|
+
d[len] = '\0';
|
119
|
+
|
120
|
+
return d;
|
121
|
+
}
|
122
|
+
|
123
|
+
VALUE
|
124
|
+
ox_utf8_name(const char *str, size_t len, rb_encoding *encoding, const char **strp) {
|
125
|
+
return ox_str_intern(str, len, strp);
|
126
|
+
}
|
127
|
+
|
128
|
+
VALUE
|
129
|
+
ox_utf8_sym(const char *str, size_t len, rb_encoding *encoding, const char **strp) {
|
130
|
+
return ox_sym_intern(str, len, strp);
|
131
|
+
}
|
132
|
+
|
133
|
+
VALUE
|
134
|
+
ox_enc_sym(const char *str, size_t len, rb_encoding *encoding, const char **strp) {
|
135
|
+
VALUE sym = rb_str_new2(str);
|
136
|
+
|
137
|
+
rb_enc_associate(sym, encoding);
|
138
|
+
if (NULL != strp) {
|
139
|
+
*strp = StringValuePtr(sym);
|
140
|
+
}
|
141
|
+
return rb_to_symbol(sym);
|
142
|
+
}
|
143
|
+
|
144
|
+
VALUE
|
145
|
+
ox_enc_name(const char *str, size_t len, rb_encoding *encoding, const char **strp) {
|
146
|
+
VALUE sym = rb_str_new2(str);
|
147
|
+
|
148
|
+
rb_enc_associate(sym, encoding);
|
149
|
+
if (NULL != strp) {
|
150
|
+
*strp = StringValuePtr(sym);
|
151
|
+
}
|
152
|
+
return sym;
|
153
|
+
}
|
data/ext/ox/intern.h
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
// Copyright (c) 2011, 2021 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
|
+
#ifndef OX_INTERN_H
|
4
|
+
#define OX_INTERN_H
|
5
|
+
|
6
|
+
#include <ruby.h>
|
7
|
+
#include <ruby/encoding.h>
|
8
|
+
|
9
|
+
struct _parseInfo;
|
10
|
+
|
11
|
+
extern void ox_hash_init();
|
12
|
+
|
13
|
+
extern VALUE ox_str_intern(const char *key, size_t len, const char **keyp);
|
14
|
+
extern VALUE ox_sym_intern(const char *key, size_t len, const char **keyp);
|
15
|
+
extern ID ox_attr_intern(const char *key, size_t len);
|
16
|
+
extern ID ox_id_intern(const char *key, size_t len);
|
17
|
+
|
18
|
+
extern char *ox_strndup(const char *s, size_t len);
|
19
|
+
|
20
|
+
extern VALUE ox_utf8_name(const char *str, size_t len, rb_encoding *encoding, const char **strp);
|
21
|
+
extern VALUE ox_utf8_sym(const char *str, size_t len, rb_encoding *encoding, const char **strp);
|
22
|
+
extern VALUE ox_enc_sym(const char *str, size_t len, rb_encoding *encoding, const char **strp);
|
23
|
+
extern VALUE ox_enc_name(const char *str, size_t len, rb_encoding *encoding, const char **strp);
|
24
|
+
|
25
|
+
#endif /* OX_INTERN_H */
|
data/ext/ox/obj_load.c
CHANGED
@@ -11,11 +11,11 @@
|
|
11
11
|
#include <time.h>
|
12
12
|
|
13
13
|
#include "ruby.h"
|
14
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
15
14
|
#include "ruby/encoding.h"
|
16
|
-
|
15
|
+
|
17
16
|
#include "base64.h"
|
18
17
|
#include "ox.h"
|
18
|
+
#include "intern.h"
|
19
19
|
|
20
20
|
static void instruct(PInfo pi, const char *target, Attr attrs, const char *content);
|
21
21
|
static void add_text(PInfo pi, char *text, int closed);
|
@@ -56,56 +56,6 @@ ParseCallbacks ox_obj_callbacks = &_ox_obj_callbacks;
|
|
56
56
|
|
57
57
|
extern ParseCallbacks ox_gen_callbacks;
|
58
58
|
|
59
|
-
|
60
|
-
inline static VALUE
|
61
|
-
str2sym(const char *str, void *encoding) {
|
62
|
-
VALUE sym;
|
63
|
-
|
64
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
65
|
-
if (0 != encoding) {
|
66
|
-
VALUE rstr = rb_str_new2(str);
|
67
|
-
|
68
|
-
rb_enc_associate(rstr, (rb_encoding*)encoding);
|
69
|
-
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
70
|
-
} else {
|
71
|
-
sym = ID2SYM(rb_intern(str));
|
72
|
-
}
|
73
|
-
#else
|
74
|
-
sym = ID2SYM(rb_intern(str));
|
75
|
-
#endif
|
76
|
-
return sym;
|
77
|
-
}
|
78
|
-
|
79
|
-
inline static ID
|
80
|
-
name2var(const char *name, void *encoding) {
|
81
|
-
VALUE *slot;
|
82
|
-
ID var_id = 0;
|
83
|
-
|
84
|
-
if ('0' <= *name && *name <= '9') {
|
85
|
-
var_id = INT2NUM(atoi(name));
|
86
|
-
} else if (Qundef == (var_id = ox_cache_get(ox_attr_cache, name, &slot, 0))) {
|
87
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
88
|
-
if (0 != encoding) {
|
89
|
-
volatile VALUE rstr = rb_str_new2(name);
|
90
|
-
volatile VALUE sym;
|
91
|
-
|
92
|
-
rb_enc_associate(rstr, (rb_encoding*)encoding);
|
93
|
-
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
94
|
-
// Needed for Ruby 2.2 to get around the GC of symbols
|
95
|
-
// created with to_sym which is needed for encoded symbols.
|
96
|
-
rb_ary_push(ox_sym_bank, sym);
|
97
|
-
var_id = SYM2ID(sym);
|
98
|
-
} else {
|
99
|
-
var_id = rb_intern(name);
|
100
|
-
}
|
101
|
-
#else
|
102
|
-
var_id = rb_intern(name);
|
103
|
-
#endif
|
104
|
-
*slot = var_id;
|
105
|
-
}
|
106
|
-
return var_id;
|
107
|
-
}
|
108
|
-
|
109
59
|
inline static VALUE
|
110
60
|
resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_class) {
|
111
61
|
VALUE clas;
|
@@ -203,7 +153,7 @@ classname2class(const char *name, PInfo pi, VALUE base_class) {
|
|
203
153
|
VALUE *slot;
|
204
154
|
VALUE clas;
|
205
155
|
|
206
|
-
if (Qundef == (clas =
|
156
|
+
if (Qundef == (clas = slot_cache_get(ox_class_cache, name, &slot, 0))) {
|
207
157
|
char class_name[1024];
|
208
158
|
char *s;
|
209
159
|
const char *n = name;
|
@@ -228,6 +178,7 @@ classname2class(const char *name, PInfo pi, VALUE base_class) {
|
|
228
178
|
*s = '\0';
|
229
179
|
if (Qundef != (clas = resolve_classname(clas, class_name, pi->options->effort, base_class))) {
|
230
180
|
*slot = clas;
|
181
|
+
rb_gc_register_address(slot);
|
231
182
|
}
|
232
183
|
}
|
233
184
|
return clas;
|
@@ -237,8 +188,12 @@ static ID
|
|
237
188
|
get_var_sym_from_attrs(Attr a, void *encoding) {
|
238
189
|
for (; 0 != a->name; a++) {
|
239
190
|
if ('a' == *a->name && '\0' == *(a->name + 1)) {
|
240
|
-
|
241
|
-
|
191
|
+
const char *val = a->value;
|
192
|
+
|
193
|
+
if ('0' <= *val && *val <= '9') {
|
194
|
+
return INT2NUM(atoi(val));
|
195
|
+
}
|
196
|
+
return ox_id_intern(val, strlen(val));
|
242
197
|
}
|
243
198
|
}
|
244
199
|
return 0;
|
@@ -376,13 +331,11 @@ parse_regexp(const char *text) {
|
|
376
331
|
static void
|
377
332
|
instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
378
333
|
if (0 == strcmp("xml", target)) {
|
379
|
-
#if HAVE_RB_ENC_FIND
|
380
334
|
for (; 0 != attrs->name; attrs++) {
|
381
335
|
if (0 == strcmp("encoding", attrs->name)) {
|
382
336
|
pi->options->rb_enc = rb_enc_find(attrs->value);
|
383
337
|
}
|
384
338
|
}
|
385
|
-
#endif
|
386
339
|
}
|
387
340
|
}
|
388
341
|
|
@@ -408,11 +361,9 @@ add_text(PInfo pi, char *text, int closed) {
|
|
408
361
|
case NoCode:
|
409
362
|
case StringCode:
|
410
363
|
h->obj = rb_str_new2(text);
|
411
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
412
364
|
if (0 != pi->options->rb_enc) {
|
413
365
|
rb_enc_associate(h->obj, pi->options->rb_enc);
|
414
366
|
}
|
415
|
-
#endif
|
416
367
|
if (0 != pi->circ_array) {
|
417
368
|
circ_array_set(pi->circ_array, h->obj, (unsigned long)pi->id);
|
418
369
|
}
|
@@ -446,20 +397,8 @@ add_text(PInfo pi, char *text, int closed) {
|
|
446
397
|
h->obj = rb_float_new(strtod(text, 0));
|
447
398
|
break;
|
448
399
|
case SymbolCode:
|
449
|
-
|
450
|
-
VALUE sym;
|
451
|
-
VALUE *slot;
|
452
|
-
|
453
|
-
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, text, &slot, 0))) {
|
454
|
-
sym = str2sym(text, (void*)pi->options->rb_enc);
|
455
|
-
// Needed for Ruby 2.2 to get around the GC of symbols created with
|
456
|
-
// to_sym which is needed for encoded symbols.
|
457
|
-
rb_ary_push(ox_sym_bank, sym);
|
458
|
-
*slot = sym;
|
459
|
-
}
|
460
|
-
h->obj = sym;
|
400
|
+
h->obj = ox_sym_intern(text, strlen(text), NULL);
|
461
401
|
break;
|
462
|
-
}
|
463
402
|
case DateCode:
|
464
403
|
{
|
465
404
|
VALUE args[1];
|
@@ -481,11 +420,9 @@ add_text(PInfo pi, char *text, int closed) {
|
|
481
420
|
|
482
421
|
from_base64(text, (uchar*)str);
|
483
422
|
v = rb_str_new(str, str_size);
|
484
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
485
423
|
if (0 != pi->options->rb_enc) {
|
486
424
|
rb_enc_associate(v, pi->options->rb_enc);
|
487
425
|
}
|
488
|
-
#endif
|
489
426
|
if (0 != pi->circ_array) {
|
490
427
|
circ_array_set(pi->circ_array, v, (unsigned long)h->obj);
|
491
428
|
}
|
@@ -494,20 +431,11 @@ add_text(PInfo pi, char *text, int closed) {
|
|
494
431
|
}
|
495
432
|
case Symbol64Code:
|
496
433
|
{
|
497
|
-
VALUE sym;
|
498
|
-
VALUE *slot;
|
499
434
|
unsigned long str_size = b64_orig_size(text);
|
500
435
|
char *str = ALLOCA_N(char, str_size + 1);
|
501
436
|
|
502
437
|
from_base64(text, (uchar*)str);
|
503
|
-
|
504
|
-
sym = str2sym(str, (void*)pi->options->rb_enc);
|
505
|
-
// Needed for Ruby 2.2 to get around the GC of symbols created with
|
506
|
-
// to_sym which is needed for encoded symbols.
|
507
|
-
rb_ary_push(ox_sym_bank, sym);
|
508
|
-
*slot = sym;
|
509
|
-
}
|
510
|
-
h->obj = sym;
|
438
|
+
h->obj = ox_sym_intern(str, strlen(str), NULL);
|
511
439
|
break;
|
512
440
|
}
|
513
441
|
case RegexpCode:
|
@@ -843,7 +771,7 @@ parse_double_time(const char *text, VALUE clas) {
|
|
843
771
|
for (; text - dot <= 9; text++) {
|
844
772
|
v2 *= 10;
|
845
773
|
}
|
846
|
-
#if
|
774
|
+
#if HAVE_RB_TIME_NANO_NEW
|
847
775
|
return rb_time_nano_new(v, v2);
|
848
776
|
#else
|
849
777
|
return rb_time_new(v, v2 / 1000);
|
@@ -899,7 +827,7 @@ parse_xsd_time(const char *text, VALUE clas) {
|
|
899
827
|
tm.tm_hour = (int)cargs[3];
|
900
828
|
tm.tm_min = (int)cargs[4];
|
901
829
|
tm.tm_sec = (int)cargs[5];
|
902
|
-
#if
|
830
|
+
#if HAVE_RB_TIME_NANO_NEW
|
903
831
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
904
832
|
#else
|
905
833
|
return rb_time_new(mktime(&tm), cargs[6] / 1000);
|