ox 2.14.7 → 2.14.10
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 +18 -0
- data/ext/ox/buf.h +8 -0
- data/ext/ox/cache.c +15 -26
- data/ext/ox/cache.h +7 -9
- data/ext/ox/intern.c +26 -31
- data/ext/ox/obj_load.c +2 -1
- data/ext/ox/ox.c +2 -6
- data/ext/ox/ox.h +2 -4
- data/ext/ox/parse.c +1 -1
- data/ext/ox/sax.c +22 -9
- data/ext/ox/slotcache.c +158 -0
- data/ext/ox/slotcache.h +19 -0
- data/lib/ox/version.rb +1 -1
- metadata +4 -4
- data/ext/ox/oxcache.c +0 -160
- data/ext/ox/oxcache.h +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6a58bfa91298fd0da2d02538dfe039bb5a426edfba8e4f245d8bd91b7388cbb
|
4
|
+
data.tar.gz: 77765350035814045329fa94935cd3de29975eaefbaef1666e4ffe29269338d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ac7c0bd9c0ac54cd033f432a0e14cd29b265b078459025c889ca08a907703d1aa202aee9ccae792e87a47b783bacf3044e62bedfc0c25090457dd5035ee2ee3
|
7
|
+
data.tar.gz: 73fc0775f561ca3290b6f6a875d0c8076d4434a642f0c0e7321952ed8b1adc655aa0f880916e1fde5f02f0d29b5c7cc57de871e4e58c869540c219bd46d75403
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,24 @@
|
|
2
2
|
|
3
3
|
All changes to the Ox gem are documented here. Releases follow semantic versioning.
|
4
4
|
|
5
|
+
## [2.14.10] - 2022-03-10
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
|
9
|
+
- Writing strings over 16K to a file with builder no longer causes a crash.
|
10
|
+
|
11
|
+
## [2.14.9] - 2022-02-11
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
|
15
|
+
- Fixed the `\r` replacement with `\n` with the SAX parser according to https://www.w3.org/TR/2008/REC-xml-20081126/#sec-line-ends.
|
16
|
+
|
17
|
+
## [2.14.8] - 2022-02-09
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
|
21
|
+
- Renamed internal functions to avoid linking issues where Oj and Ox function names collided.
|
22
|
+
|
5
23
|
## [2.14.7] - 2022-02-03
|
6
24
|
|
7
25
|
### Fixed
|
data/ext/ox/buf.h
CHANGED
@@ -86,8 +86,16 @@ buf_append_string(Buf buf, const char *s, size_t slen) {
|
|
86
86
|
|
87
87
|
if (len != (size_t)write(buf->fd, buf->head, len)) {
|
88
88
|
buf->err = true;
|
89
|
+
return;
|
89
90
|
}
|
90
91
|
buf->tail = buf->head;
|
92
|
+
if (sizeof(buf->base) <= slen) {
|
93
|
+
if (slen != (size_t)write(buf->fd, s, slen)) {
|
94
|
+
buf->err = true;
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
return;
|
98
|
+
}
|
91
99
|
} else {
|
92
100
|
size_t len = buf->end - buf->head;
|
93
101
|
size_t toff = buf->tail - buf->head;
|
data/ext/ox/cache.c
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
#define M 0x5bd1e995
|
29
29
|
|
30
30
|
typedef struct _slot {
|
31
|
-
struct _slot
|
31
|
+
struct _slot *next;
|
32
32
|
VALUE val;
|
33
33
|
uint64_t hash;
|
34
34
|
volatile uint32_t use_cnt;
|
@@ -37,7 +37,7 @@ typedef struct _slot {
|
|
37
37
|
} * Slot;
|
38
38
|
|
39
39
|
typedef struct _cache {
|
40
|
-
volatile Slot
|
40
|
+
volatile Slot *slots;
|
41
41
|
volatile size_t cnt;
|
42
42
|
VALUE (*form)(const char *str, size_t len);
|
43
43
|
uint64_t size;
|
@@ -54,10 +54,6 @@ typedef struct _cache {
|
|
54
54
|
bool mark;
|
55
55
|
} * Cache;
|
56
56
|
|
57
|
-
void cache_set_form(Cache c, VALUE (*form)(const char *str, size_t len)) {
|
58
|
-
c->form = form;
|
59
|
-
}
|
60
|
-
|
61
57
|
static uint64_t hash_calc(const uint8_t *key, size_t len) {
|
62
58
|
const uint8_t *end = key + len;
|
63
59
|
const uint8_t *endless = key + (len & 0xFFFFFFFC);
|
@@ -94,8 +90,8 @@ static uint64_t hash_calc(const uint8_t *key, size_t len) {
|
|
94
90
|
|
95
91
|
static void rehash(Cache c) {
|
96
92
|
uint64_t osize;
|
97
|
-
Slot
|
98
|
-
Slot
|
93
|
+
Slot *end;
|
94
|
+
Slot *sp;
|
99
95
|
|
100
96
|
osize = c->size;
|
101
97
|
c->size = osize * 4;
|
@@ -110,7 +106,7 @@ static void rehash(Cache c) {
|
|
110
106
|
*sp = NULL;
|
111
107
|
for (; NULL != s; s = next) {
|
112
108
|
uint64_t h = s->hash & c->mask;
|
113
|
-
Slot
|
109
|
+
Slot *bucket = (Slot *)c->slots + h;
|
114
110
|
|
115
111
|
next = s->next;
|
116
112
|
s->next = *bucket;
|
@@ -119,9 +115,9 @@ static void rehash(Cache c) {
|
|
119
115
|
}
|
120
116
|
}
|
121
117
|
|
122
|
-
static VALUE
|
118
|
+
static VALUE ox_lockless_intern(Cache c, const char *key, size_t len, const char **keyp) {
|
123
119
|
uint64_t h = hash_calc((const uint8_t *)key, len);
|
124
|
-
Slot
|
120
|
+
Slot *bucket = (Slot *)c->slots + (h & c->mask);
|
125
121
|
Slot b;
|
126
122
|
volatile VALUE rkey;
|
127
123
|
|
@@ -169,9 +165,9 @@ static VALUE lockless_intern(Cache c, const char *key, size_t len, const char **
|
|
169
165
|
return rkey;
|
170
166
|
}
|
171
167
|
|
172
|
-
static VALUE
|
168
|
+
static VALUE ox_locking_intern(Cache c, const char *key, size_t len, const char **keyp) {
|
173
169
|
uint64_t h;
|
174
|
-
Slot
|
170
|
+
Slot *bucket;
|
175
171
|
Slot b;
|
176
172
|
uint64_t old_size;
|
177
173
|
volatile VALUE rkey;
|
@@ -239,10 +235,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len, const char **k
|
|
239
235
|
return rkey;
|
240
236
|
}
|
241
237
|
|
242
|
-
Cache
|
243
|
-
VALUE (*form)(const char *str, size_t len),
|
244
|
-
bool mark,
|
245
|
-
bool locking) {
|
238
|
+
Cache ox_cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark, bool locking) {
|
246
239
|
Cache c = calloc(1, sizeof(struct _cache));
|
247
240
|
int shift = 0;
|
248
241
|
|
@@ -263,18 +256,14 @@ Cache cache_create(size_t size,
|
|
263
256
|
c->xrate = 1; // low
|
264
257
|
c->mark = mark;
|
265
258
|
if (locking) {
|
266
|
-
c->intern =
|
259
|
+
c->intern = ox_locking_intern;
|
267
260
|
} else {
|
268
|
-
c->intern =
|
261
|
+
c->intern = ox_lockless_intern;
|
269
262
|
}
|
270
263
|
return c;
|
271
264
|
}
|
272
265
|
|
273
|
-
void
|
274
|
-
c->xrate = (uint8_t)rate;
|
275
|
-
}
|
276
|
-
|
277
|
-
void cache_free(Cache c) {
|
266
|
+
void ox_cache_free(Cache c) {
|
278
267
|
uint64_t i;
|
279
268
|
|
280
269
|
for (i = 0; i < c->size; i++) {
|
@@ -290,7 +279,7 @@ void cache_free(Cache c) {
|
|
290
279
|
free(c);
|
291
280
|
}
|
292
281
|
|
293
|
-
void
|
282
|
+
void ox_cache_mark(Cache c) {
|
294
283
|
uint64_t i;
|
295
284
|
|
296
285
|
#if !HAVE_PTHREAD_MUTEX_INIT
|
@@ -333,7 +322,7 @@ void cache_mark(Cache c) {
|
|
333
322
|
}
|
334
323
|
|
335
324
|
VALUE
|
336
|
-
|
325
|
+
ox_cache_intern(Cache c, const char *key, size_t len, const char **keyp) {
|
337
326
|
if (CACHE_MAX_KEY <= len) {
|
338
327
|
if (NULL != keyp) {
|
339
328
|
volatile VALUE rkey = c->form(key, len);
|
data/ext/ox/cache.h
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
// Copyright (c) 2021 Peter Ohler. All rights reserved.
|
2
2
|
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
3
|
|
4
|
-
#ifndef
|
5
|
-
#define
|
4
|
+
#ifndef OX_CACHE_H
|
5
|
+
#define OX_CACHE_H
|
6
6
|
|
7
7
|
#include <ruby.h>
|
8
8
|
#include <stdbool.h>
|
@@ -11,11 +11,9 @@
|
|
11
11
|
|
12
12
|
struct _cache;
|
13
13
|
|
14
|
-
extern struct _cache *
|
15
|
-
extern void
|
16
|
-
extern void
|
17
|
-
extern
|
18
|
-
extern VALUE cache_intern(struct _cache *c, const char *key, size_t len, const char **keyp);
|
19
|
-
extern void cache_set_expunge_rate(struct _cache *c, int rate);
|
14
|
+
extern struct _cache *ox_cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark, bool locking);
|
15
|
+
extern void ox_cache_free(struct _cache *c);
|
16
|
+
extern void ox_cache_mark(struct _cache *c);
|
17
|
+
extern VALUE ox_cache_intern(struct _cache *c, const char *key, size_t len, const char **keyp);
|
20
18
|
|
21
|
-
#endif /*
|
19
|
+
#endif /* OX_CACHE_H */
|
data/ext/ox/intern.c
CHANGED
@@ -8,17 +8,19 @@
|
|
8
8
|
#include "cache.h"
|
9
9
|
#include "ox.h"
|
10
10
|
|
11
|
-
|
12
|
-
|
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;
|
13
15
|
|
14
|
-
static struct _cache *
|
15
|
-
static VALUE
|
16
|
+
static struct _cache *ox_sym_cache = NULL;
|
17
|
+
static VALUE ox_sym_cache_obj;
|
16
18
|
|
17
|
-
static struct _cache *
|
18
|
-
static VALUE
|
19
|
+
static struct _cache *ox_attr_cache = NULL;
|
20
|
+
static VALUE ox_attr_cache_obj;
|
19
21
|
|
20
|
-
static struct _cache *
|
21
|
-
static VALUE
|
22
|
+
static struct _cache *ox_id_cache = NULL;
|
23
|
+
static VALUE ox_id_cache_obj;
|
22
24
|
|
23
25
|
static VALUE form_str(const char *str, size_t len) {
|
24
26
|
return rb_str_freeze(rb_utf8_str_new(str, len));
|
@@ -67,21 +69,21 @@ static VALUE form_id(const char *str, size_t len) {
|
|
67
69
|
void ox_hash_init() {
|
68
70
|
VALUE cache_class = rb_define_class_under(Ox, "Cache", rb_cObject);
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
rb_gc_register_address(&
|
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);
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
rb_gc_register_address(&
|
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);
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
rb_gc_register_address(&
|
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);
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
rb_gc_register_address(&
|
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);
|
85
87
|
}
|
86
88
|
|
87
89
|
VALUE
|
@@ -92,21 +94,21 @@ ox_str_intern(const char *key, size_t len, const char **keyp) {
|
|
92
94
|
#if HAVE_RB_ENC_INTERNED_STR && 0
|
93
95
|
return rb_enc_interned_str(key, len, rb_utf8_encoding());
|
94
96
|
#else
|
95
|
-
return
|
97
|
+
return ox_cache_intern(ox_str_cache, key, len, keyp);
|
96
98
|
#endif
|
97
99
|
}
|
98
100
|
|
99
101
|
VALUE
|
100
102
|
ox_sym_intern(const char *key, size_t len, const char **keyp) {
|
101
|
-
return
|
103
|
+
return ox_cache_intern(ox_sym_cache, key, len, keyp);
|
102
104
|
}
|
103
105
|
|
104
106
|
ID ox_attr_intern(const char *key, size_t len) {
|
105
|
-
return
|
107
|
+
return ox_cache_intern(ox_attr_cache, key, len, NULL);
|
106
108
|
}
|
107
109
|
|
108
110
|
ID ox_id_intern(const char *key, size_t len) {
|
109
|
-
return
|
111
|
+
return ox_cache_intern(ox_id_cache, key, len, NULL);
|
110
112
|
}
|
111
113
|
|
112
114
|
char *ox_strndup(const char *s, size_t len) {
|
@@ -118,13 +120,6 @@ char *ox_strndup(const char *s, size_t len) {
|
|
118
120
|
return d;
|
119
121
|
}
|
120
122
|
|
121
|
-
void intern_cleanup() {
|
122
|
-
cache_free(str_cache);
|
123
|
-
cache_free(sym_cache);
|
124
|
-
cache_free(attr_cache);
|
125
|
-
cache_free(id_cache);
|
126
|
-
}
|
127
|
-
|
128
123
|
VALUE
|
129
124
|
ox_utf8_name(const char *str, size_t len, rb_encoding *encoding, const char **strp) {
|
130
125
|
return ox_str_intern(str, len, strp);
|
data/ext/ox/obj_load.c
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
|
13
13
|
#include "ruby.h"
|
14
14
|
#include "ruby/encoding.h"
|
15
|
+
|
15
16
|
#include "base64.h"
|
16
17
|
#include "ox.h"
|
17
18
|
#include "intern.h"
|
@@ -152,7 +153,7 @@ classname2class(const char *name, PInfo pi, VALUE base_class) {
|
|
152
153
|
VALUE *slot;
|
153
154
|
VALUE clas;
|
154
155
|
|
155
|
-
if (Qundef == (clas =
|
156
|
+
if (Qundef == (clas = slot_cache_get(ox_class_cache, name, &slot, 0))) {
|
156
157
|
char class_name[1024];
|
157
158
|
char *s;
|
158
159
|
const char *n = name;
|
data/ext/ox/ox.c
CHANGED
@@ -107,9 +107,7 @@ VALUE ox_struct_class;
|
|
107
107
|
VALUE ox_syntax_error_class;
|
108
108
|
VALUE ox_time_class;
|
109
109
|
|
110
|
-
|
111
|
-
Cache ox_class_cache = 0;
|
112
|
-
Cache ox_attr_cache = 0;
|
110
|
+
SlotCache ox_class_cache = 0;
|
113
111
|
|
114
112
|
static VALUE abort_sym;
|
115
113
|
static VALUE active_sym;
|
@@ -1646,9 +1644,7 @@ void Init_ox() {
|
|
1646
1644
|
rb_gc_register_address(&ox_time_class);
|
1647
1645
|
rb_gc_register_address(&ox_version_sym);
|
1648
1646
|
|
1649
|
-
|
1650
|
-
ox_cache_new(&ox_class_cache);
|
1651
|
-
ox_cache_new(&ox_attr_cache);
|
1647
|
+
slot_cache_new(&ox_class_cache);
|
1652
1648
|
|
1653
1649
|
ox_sax_define();
|
1654
1650
|
ox_hash_init();
|
data/ext/ox/ox.h
CHANGED
@@ -28,7 +28,7 @@ extern "C" {
|
|
28
28
|
#include "attr.h"
|
29
29
|
#include "err.h"
|
30
30
|
#include "helper.h"
|
31
|
-
#include "
|
31
|
+
#include "slotcache.h"
|
32
32
|
#include "type.h"
|
33
33
|
|
34
34
|
#define raise_error(msg, xml, current) _ox_raise_error(msg, xml, current, __FILE__, __LINE__)
|
@@ -238,9 +238,7 @@ extern VALUE ox_raw_clas;
|
|
238
238
|
extern VALUE ox_doctype_clas;
|
239
239
|
extern VALUE ox_cdata_clas;
|
240
240
|
|
241
|
-
extern
|
242
|
-
extern Cache ox_class_cache;
|
243
|
-
extern Cache ox_attr_cache;
|
241
|
+
extern SlotCache ox_class_cache;
|
244
242
|
|
245
243
|
extern void ox_init_builder(VALUE ox);
|
246
244
|
|
data/ext/ox/parse.c
CHANGED
data/ext/ox/sax.c
CHANGED
@@ -307,8 +307,8 @@ static void sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, SaxOptions opti
|
|
307
307
|
dr->encoding = rb_enc_find(ox_default_options.encoding);
|
308
308
|
}
|
309
309
|
dr->utf8 = (NULL == dr->encoding || rb_utf8_encoding() == dr->encoding);
|
310
|
-
if (NULL == dr->encoding || rb_utf8_encoding() == dr->encoding) {
|
311
|
-
dr->get_name = dr->options.symbolize ? ox_utf8_sym : ox_utf8_name;
|
310
|
+
if (NULL == dr->encoding || rb_utf8_encoding() == dr->encoding) { // UTF-8
|
311
|
+
dr->get_name = dr->options.symbolize ? ox_utf8_sym : ox_utf8_name; // TBD UTF8 sym?
|
312
312
|
} else {
|
313
313
|
dr->get_name = dr->options.symbolize ? ox_enc_sym : ox_enc_name;
|
314
314
|
}
|
@@ -334,7 +334,7 @@ static char skipBOM(SaxDrive dr) {
|
|
334
334
|
if (0xEF == (uint8_t)c) { /* only UTF8 is supported */
|
335
335
|
if (0xBB == (uint8_t)buf_get(&dr->buf) && 0xBF == (uint8_t)buf_get(&dr->buf)) {
|
336
336
|
dr->encoding = ox_utf8_encoding;
|
337
|
-
c
|
337
|
+
c = buf_get(&dr->buf);
|
338
338
|
} else {
|
339
339
|
ox_sax_drive_error(dr, BAD_BOM "invalid BOM or a binary file.");
|
340
340
|
c = '\0';
|
@@ -1217,7 +1217,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
|
|
1217
1217
|
attr_value = dr->buf.str;
|
1218
1218
|
if (is_encoding) {
|
1219
1219
|
dr->encoding = rb_enc_find(dr->buf.str);
|
1220
|
-
is_encoding
|
1220
|
+
is_encoding = 0;
|
1221
1221
|
}
|
1222
1222
|
}
|
1223
1223
|
if (0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay || NestOverlay == h->overlay)) {
|
@@ -1368,7 +1368,8 @@ int ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long co
|
|
1368
1368
|
char *b = str;
|
1369
1369
|
|
1370
1370
|
while ('\0' != *s) {
|
1371
|
-
|
1371
|
+
switch (*s) {
|
1372
|
+
case '&': {
|
1372
1373
|
int c = 0;
|
1373
1374
|
char *end;
|
1374
1375
|
|
@@ -1458,13 +1459,25 @@ int ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long co
|
|
1458
1459
|
}
|
1459
1460
|
*b++ = (char)c;
|
1460
1461
|
col++;
|
1461
|
-
|
1462
|
+
break;
|
1463
|
+
}
|
1464
|
+
case '\r':
|
1465
|
+
s++;
|
1462
1466
|
if ('\n' == *s) {
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1467
|
+
continue;
|
1468
|
+
}
|
1469
|
+
line++;
|
1470
|
+
col = 1;
|
1471
|
+
*b++ = '\n';
|
1472
|
+
break;
|
1473
|
+
case '\n':
|
1474
|
+
line++;
|
1475
|
+
col = 0;
|
1476
|
+
// fall through
|
1477
|
+
default:
|
1466
1478
|
col++;
|
1467
1479
|
*b++ = *s++;
|
1480
|
+
break;
|
1468
1481
|
}
|
1469
1482
|
}
|
1470
1483
|
*b = '\0';
|
data/ext/ox/slotcache.c
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
/* slotcache.c
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "slotcache.h"
|
7
|
+
|
8
|
+
#include <errno.h>
|
9
|
+
#include <stdarg.h>
|
10
|
+
#include <stdint.h>
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h>
|
14
|
+
#include <strings.h>
|
15
|
+
|
16
|
+
struct _slotCache {
|
17
|
+
/* The key is a length byte followed by the key as a string. If the key is longer than 254 characters then the
|
18
|
+
length is 255. The key can be for a premature value and in that case the length byte is greater than the length
|
19
|
+
of the key. */
|
20
|
+
char *key;
|
21
|
+
VALUE value;
|
22
|
+
struct _slotCache *slots[16];
|
23
|
+
};
|
24
|
+
|
25
|
+
static void slot_print(SlotCache cache, unsigned int depth);
|
26
|
+
|
27
|
+
static char *form_key(const char *s) {
|
28
|
+
size_t len = strlen(s);
|
29
|
+
char *d = ALLOC_N(char, len + 2);
|
30
|
+
|
31
|
+
*(uint8_t *)d = (255 <= len) ? 255 : len;
|
32
|
+
memcpy(d + 1, s, len + 1);
|
33
|
+
|
34
|
+
return d;
|
35
|
+
}
|
36
|
+
|
37
|
+
void slot_cache_new(SlotCache *cache) {
|
38
|
+
*cache = ALLOC(struct _slotCache);
|
39
|
+
(*cache)->key = 0;
|
40
|
+
(*cache)->value = Qundef;
|
41
|
+
memset((*cache)->slots, 0, sizeof((*cache)->slots));
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE
|
45
|
+
slot_cache_get(SlotCache cache, const char *key, VALUE **slot, const char **keyp) {
|
46
|
+
unsigned char *k = (unsigned char *)key;
|
47
|
+
SlotCache *cp;
|
48
|
+
|
49
|
+
for (; '\0' != *k; k++) {
|
50
|
+
cp = cache->slots + (unsigned int)(*k >> 4); /* upper 4 bits */
|
51
|
+
if (0 == *cp) {
|
52
|
+
slot_cache_new(cp);
|
53
|
+
}
|
54
|
+
cache = *cp;
|
55
|
+
cp = cache->slots + (unsigned int)(*k & 0x0F); /* lower 4 bits */
|
56
|
+
if (0 == *cp) { /* nothing on this tree so set key and value as a premature key/value pair */
|
57
|
+
slot_cache_new(cp);
|
58
|
+
cache = *cp;
|
59
|
+
cache->key = form_key(key);
|
60
|
+
break;
|
61
|
+
} else {
|
62
|
+
int depth = (int)(k - (unsigned char *)key + 1);
|
63
|
+
|
64
|
+
cache = *cp;
|
65
|
+
|
66
|
+
if ('\0' == *(k + 1)) { /* exact match */
|
67
|
+
if (0 == cache->key) { /* nothing in this spot so take it */
|
68
|
+
cache->key = form_key(key);
|
69
|
+
break;
|
70
|
+
} else if ((depth == *cache->key || 255 < depth) && 0 == strcmp(key, cache->key + 1)) { /* match */
|
71
|
+
break;
|
72
|
+
} else { /* have to move the current premature key/value deeper */
|
73
|
+
unsigned char *ck = (unsigned char *)(cache->key + depth + 1);
|
74
|
+
SlotCache orig = *cp;
|
75
|
+
|
76
|
+
cp = (*cp)->slots + (*ck >> 4);
|
77
|
+
slot_cache_new(cp);
|
78
|
+
cp = (*cp)->slots + (*ck & 0x0F);
|
79
|
+
slot_cache_new(cp);
|
80
|
+
(*cp)->key = cache->key;
|
81
|
+
(*cp)->value = cache->value;
|
82
|
+
orig->key = form_key(key);
|
83
|
+
orig->value = Qundef;
|
84
|
+
}
|
85
|
+
} else { /* not exact match but on the path */
|
86
|
+
if (0 != cache->key) { /* there is a key/value here already */
|
87
|
+
if (depth == *cache->key || (255 <= depth && 0 == strncmp(cache->key, key, depth) &&
|
88
|
+
'\0' == cache->key[depth])) { /* key belongs here */
|
89
|
+
continue;
|
90
|
+
} else {
|
91
|
+
unsigned char *ck = (unsigned char *)(cache->key + depth + 1);
|
92
|
+
SlotCache orig = *cp;
|
93
|
+
|
94
|
+
cp = (*cp)->slots + (*ck >> 4);
|
95
|
+
slot_cache_new(cp);
|
96
|
+
cp = (*cp)->slots + (*ck & 0x0F);
|
97
|
+
slot_cache_new(cp);
|
98
|
+
(*cp)->key = cache->key;
|
99
|
+
(*cp)->value = cache->value;
|
100
|
+
orig->key = 0;
|
101
|
+
orig->value = Qundef;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
*slot = &cache->value;
|
108
|
+
if (0 != keyp) {
|
109
|
+
if (0 == cache->key) {
|
110
|
+
printf("*** Error: failed to set the key for '%s'\n", key);
|
111
|
+
*keyp = 0;
|
112
|
+
} else {
|
113
|
+
*keyp = cache->key + 1;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
return cache->value;
|
117
|
+
}
|
118
|
+
|
119
|
+
void slot_cache_print(SlotCache cache) {
|
120
|
+
/*printf("-------------------------------------------\n");*/
|
121
|
+
slot_print(cache, 0);
|
122
|
+
}
|
123
|
+
|
124
|
+
static void slot_print(SlotCache c, unsigned int depth) {
|
125
|
+
char indent[256];
|
126
|
+
SlotCache *cp;
|
127
|
+
unsigned int i;
|
128
|
+
|
129
|
+
if (sizeof(indent) - 1 < depth) {
|
130
|
+
depth = ((int)sizeof(indent) - 1);
|
131
|
+
}
|
132
|
+
memset(indent, ' ', depth);
|
133
|
+
indent[depth] = '\0';
|
134
|
+
for (i = 0, cp = c->slots; i < 16; i++, cp++) {
|
135
|
+
if (0 == *cp) {
|
136
|
+
/*printf("%s%02u:\n", indent, i);*/
|
137
|
+
} else {
|
138
|
+
if (0 == (*cp)->key && Qundef == (*cp)->value) {
|
139
|
+
printf("%s%02u:\n", indent, i);
|
140
|
+
} else {
|
141
|
+
const char *vs;
|
142
|
+
const char *clas;
|
143
|
+
|
144
|
+
if (Qundef == (*cp)->value) {
|
145
|
+
vs = "undefined";
|
146
|
+
clas = "";
|
147
|
+
} else {
|
148
|
+
VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
|
149
|
+
|
150
|
+
vs = StringValuePtr(rs);
|
151
|
+
clas = rb_class2name(rb_obj_class((*cp)->value));
|
152
|
+
}
|
153
|
+
printf("%s%02u: %s = %s (%s)\n", indent, i, (*cp)->key, vs, clas);
|
154
|
+
}
|
155
|
+
slot_print(*cp, depth + 2);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
data/ext/ox/slotcache.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/* slotcache.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef SLOT_CACHE_H
|
7
|
+
#define SLOT_CACHE_H
|
8
|
+
|
9
|
+
#include "ruby.h"
|
10
|
+
|
11
|
+
typedef struct _slotCache *SlotCache;
|
12
|
+
|
13
|
+
extern void slot_cache_new(SlotCache *cache);
|
14
|
+
|
15
|
+
extern VALUE slot_cache_get(SlotCache cache, const char *key, VALUE **slot, const char **keyp);
|
16
|
+
|
17
|
+
extern void slot_cache_print(SlotCache cache);
|
18
|
+
|
19
|
+
#endif /* SLOT_CACHE_H */
|
data/lib/ox/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.14.
|
4
|
+
version: 2.14.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
|
14
14
|
XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
|
@@ -46,8 +46,6 @@ files:
|
|
46
46
|
- ext/ox/obj_load.c
|
47
47
|
- ext/ox/ox.c
|
48
48
|
- ext/ox/ox.h
|
49
|
-
- ext/ox/oxcache.c
|
50
|
-
- ext/ox/oxcache.h
|
51
49
|
- ext/ox/parse.c
|
52
50
|
- ext/ox/sax.c
|
53
51
|
- ext/ox/sax.h
|
@@ -57,6 +55,8 @@ files:
|
|
57
55
|
- ext/ox/sax_hint.c
|
58
56
|
- ext/ox/sax_hint.h
|
59
57
|
- ext/ox/sax_stack.h
|
58
|
+
- ext/ox/slotcache.c
|
59
|
+
- ext/ox/slotcache.h
|
60
60
|
- ext/ox/special.c
|
61
61
|
- ext/ox/special.h
|
62
62
|
- ext/ox/type.h
|
data/ext/ox/oxcache.c
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
/* cache.c
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#include <stdlib.h>
|
7
|
-
#include <errno.h>
|
8
|
-
#include <stdio.h>
|
9
|
-
#include <string.h>
|
10
|
-
#include <strings.h>
|
11
|
-
#include <stdarg.h>
|
12
|
-
#include <stdint.h>
|
13
|
-
|
14
|
-
#include "oxcache.h"
|
15
|
-
|
16
|
-
struct _cache {
|
17
|
-
/* The key is a length byte followed by the key as a string. If the key is longer than 254 characters then the
|
18
|
-
length is 255. The key can be for a premature value and in that case the length byte is greater than the length
|
19
|
-
of the key. */
|
20
|
-
char *key;
|
21
|
-
VALUE value;
|
22
|
-
struct _cache *slots[16];
|
23
|
-
};
|
24
|
-
|
25
|
-
static void slot_print(Cache cache, unsigned int depth);
|
26
|
-
|
27
|
-
static char* form_key(const char *s) {
|
28
|
-
size_t len = strlen(s);
|
29
|
-
char *d = ALLOC_N(char, len + 2);
|
30
|
-
|
31
|
-
*(uint8_t*)d = (255 <= len) ? 255 : len;
|
32
|
-
memcpy(d + 1, s, len + 1);
|
33
|
-
|
34
|
-
return d;
|
35
|
-
}
|
36
|
-
|
37
|
-
void
|
38
|
-
ox_cache_new(Cache *cache) {
|
39
|
-
*cache = ALLOC(struct _cache);
|
40
|
-
(*cache)->key = 0;
|
41
|
-
(*cache)->value = Qundef;
|
42
|
-
memset((*cache)->slots, 0, sizeof((*cache)->slots));
|
43
|
-
}
|
44
|
-
|
45
|
-
VALUE
|
46
|
-
ox_cache_get(Cache cache, const char *key, VALUE **slot, const char **keyp) {
|
47
|
-
unsigned char *k = (unsigned char*)key;
|
48
|
-
Cache *cp;
|
49
|
-
|
50
|
-
for (; '\0' != *k; k++) {
|
51
|
-
cp = cache->slots + (unsigned int)(*k >> 4); /* upper 4 bits */
|
52
|
-
if (0 == *cp) {
|
53
|
-
ox_cache_new(cp);
|
54
|
-
}
|
55
|
-
cache = *cp;
|
56
|
-
cp = cache->slots + (unsigned int)(*k & 0x0F); /* lower 4 bits */
|
57
|
-
if (0 == *cp) { /* nothing on this tree so set key and value as a premature key/value pair */
|
58
|
-
ox_cache_new(cp);
|
59
|
-
cache = *cp;
|
60
|
-
cache->key = form_key(key);
|
61
|
-
break;
|
62
|
-
} else {
|
63
|
-
int depth = (int)(k - (unsigned char*)key + 1);
|
64
|
-
|
65
|
-
cache = *cp;
|
66
|
-
|
67
|
-
if ('\0' == *(k + 1)) { /* exact match */
|
68
|
-
if (0 == cache->key) { /* nothing in this spot so take it */
|
69
|
-
cache->key = form_key(key);
|
70
|
-
break;
|
71
|
-
} else if ((depth == *cache->key || 255 < depth) && 0 == strcmp(key, cache->key + 1)) { /* match */
|
72
|
-
break;
|
73
|
-
} else { /* have to move the current premature key/value deeper */
|
74
|
-
unsigned char *ck = (unsigned char*)(cache->key + depth + 1);
|
75
|
-
Cache orig = *cp;
|
76
|
-
|
77
|
-
cp = (*cp)->slots + (*ck >> 4);
|
78
|
-
ox_cache_new(cp);
|
79
|
-
cp = (*cp)->slots + (*ck & 0x0F);
|
80
|
-
ox_cache_new(cp);
|
81
|
-
(*cp)->key = cache->key;
|
82
|
-
(*cp)->value = cache->value;
|
83
|
-
orig->key = form_key(key);
|
84
|
-
orig->value = Qundef;
|
85
|
-
}
|
86
|
-
} else { /* not exact match but on the path */
|
87
|
-
if (0 != cache->key) { /* there is a key/value here already */
|
88
|
-
if (depth == *cache->key || (255 <= depth && 0 == strncmp(cache->key, key, depth) && '\0' == cache->key[depth])) { /* key belongs here */
|
89
|
-
continue;
|
90
|
-
} else {
|
91
|
-
unsigned char *ck = (unsigned char*)(cache->key + depth + 1);
|
92
|
-
Cache orig = *cp;
|
93
|
-
|
94
|
-
cp = (*cp)->slots + (*ck >> 4);
|
95
|
-
ox_cache_new(cp);
|
96
|
-
cp = (*cp)->slots + (*ck & 0x0F);
|
97
|
-
ox_cache_new(cp);
|
98
|
-
(*cp)->key = cache->key;
|
99
|
-
(*cp)->value = cache->value;
|
100
|
-
orig->key = 0;
|
101
|
-
orig->value = Qundef;
|
102
|
-
}
|
103
|
-
}
|
104
|
-
}
|
105
|
-
}
|
106
|
-
}
|
107
|
-
*slot = &cache->value;
|
108
|
-
if (0 != keyp) {
|
109
|
-
if (0 == cache->key) {
|
110
|
-
printf("*** Error: failed to set the key for '%s'\n", key);
|
111
|
-
*keyp = 0;
|
112
|
-
} else {
|
113
|
-
*keyp = cache->key + 1;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
return cache->value;
|
117
|
-
}
|
118
|
-
|
119
|
-
void
|
120
|
-
ox_cache_print(Cache cache) {
|
121
|
-
/*printf("-------------------------------------------\n");*/
|
122
|
-
slot_print(cache, 0);
|
123
|
-
}
|
124
|
-
|
125
|
-
static void
|
126
|
-
slot_print(Cache c, unsigned int depth) {
|
127
|
-
char indent[256];
|
128
|
-
Cache *cp;
|
129
|
-
unsigned int i;
|
130
|
-
|
131
|
-
if (sizeof(indent) - 1 < depth) {
|
132
|
-
depth = ((int)sizeof(indent) - 1);
|
133
|
-
}
|
134
|
-
memset(indent, ' ', depth);
|
135
|
-
indent[depth] = '\0';
|
136
|
-
for (i = 0, cp = c->slots; i < 16; i++, cp++) {
|
137
|
-
if (0 == *cp) {
|
138
|
-
/*printf("%s%02u:\n", indent, i);*/
|
139
|
-
} else {
|
140
|
-
if (0 == (*cp)->key && Qundef == (*cp)->value) {
|
141
|
-
printf("%s%02u:\n", indent, i);
|
142
|
-
} else {
|
143
|
-
const char *vs;
|
144
|
-
const char *clas;
|
145
|
-
|
146
|
-
if (Qundef == (*cp)->value) {
|
147
|
-
vs = "undefined";
|
148
|
-
clas = "";
|
149
|
-
} else {
|
150
|
-
VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
|
151
|
-
|
152
|
-
vs = StringValuePtr(rs);
|
153
|
-
clas = rb_class2name(rb_obj_class((*cp)->value));
|
154
|
-
}
|
155
|
-
printf("%s%02u: %s = %s (%s)\n", indent, i, (*cp)->key, vs, clas);
|
156
|
-
}
|
157
|
-
slot_print(*cp, depth + 2);
|
158
|
-
}
|
159
|
-
}
|
160
|
-
}
|
data/ext/ox/oxcache.h
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
/* cache.h
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#ifndef OX_CACHE_H
|
7
|
-
#define OX_CACHE_H
|
8
|
-
|
9
|
-
#include "ruby.h"
|
10
|
-
|
11
|
-
typedef struct _cache *Cache;
|
12
|
-
|
13
|
-
extern void ox_cache_new(Cache *cache);
|
14
|
-
|
15
|
-
extern VALUE ox_cache_get(Cache cache, const char *key, VALUE **slot, const char **keyp);
|
16
|
-
|
17
|
-
extern void ox_cache_print(Cache cache);
|
18
|
-
|
19
|
-
#endif /* OX_CACHE_H */
|