ox 2.14.4 → 2.14.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +1 -1
- data/ext/ox/builder.c +8 -8
- 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 +5 -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 +1018 -935
- data/ext/ox/ox.h +186 -210
- data/ext/ox/parse.c +72 -31
- data/ext/ox/sax.c +1093 -1279
- 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 +11 -5
- 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);
|