ox 2.1.6 → 2.1.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ox might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +9 -7
- data/ext/ox/gen_load.c +10 -3
- data/ext/ox/obj_load.c +11 -2
- data/ext/ox/ox.c +2 -0
- data/ext/ox/ox.h +1 -0
- data/ext/ox/sax.c +88 -7
- data/ext/ox/sax_stack.h +2 -0
- data/lib/ox/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065c6a76ec5d44344dd607e266b9208f32aead7d
|
4
|
+
data.tar.gz: 242089d4a9ebe913eb825721085d1c6c8c7187f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37a3c5ff01e5e238ae83bde8cb3f722624e17b927a8005586ff5b6bba425c1980ba41a120ea8b0889c3da37fff802f42ed5980beb83290ed3c81ace4184b9050
|
7
|
+
data.tar.gz: 5b830c8b6c8e8cd8f41349c2962a7fd510c6540111e41dcb46619983e1829b47e9ae4e8323c6836e03b04530551c6dd0f5374a4d08e9bc89a6d7c7238b1f8469
|
data/README.md
CHANGED
@@ -34,7 +34,14 @@ A fast XML parser and Object marshaller as a Ruby gem.
|
|
34
34
|
|
35
35
|
## Release Notes
|
36
36
|
|
37
|
-
### Current Release 2.1.
|
37
|
+
### Current Release 2.1.7
|
38
|
+
|
39
|
+
- Empty elements such as <foo></foo> are now called back with empty text.
|
40
|
+
|
41
|
+
- Fixed GC problem that occurs with the new GC in Ruby 2.2 that garbage
|
42
|
+
collects Symbols.
|
43
|
+
|
44
|
+
### Release 2.1.6
|
38
45
|
|
39
46
|
- Update licenses. No other changes.
|
40
47
|
|
@@ -44,11 +51,6 @@ A fast XML parser and Object marshaller as a Ruby gem.
|
|
44
51
|
rb_intern(). There does not seem to be a way to force symbols created with
|
45
52
|
encoding to be pinned.
|
46
53
|
|
47
|
-
### Release 2.1.4
|
48
|
-
|
49
|
-
- Fixed bug where the parser always started at the first position in a stringio
|
50
|
-
instead of the current position.
|
51
|
-
|
52
54
|
## Description
|
53
55
|
|
54
56
|
Optimized XML (Ox), as the name implies was written to provide speed optimized
|
@@ -89,7 +91,7 @@ callbacks. Unlike Nokogiri and LibXML, Ox can be tuned to use only the SAX
|
|
89
91
|
callbacks that are of interest to the caller. (See the perf_sax.rb file for an
|
90
92
|
example.)
|
91
93
|
|
92
|
-
Ox is compatible with Ruby 1.8.7, 1.9.3, 2.1.2, and RBX.
|
94
|
+
Ox is compatible with Ruby 1.8.7, 1.9.3, 2.1.2, 2.2.0 and RBX.
|
93
95
|
|
94
96
|
### Object Dump Sample:
|
95
97
|
|
data/ext/ox/gen_load.c
CHANGED
@@ -300,13 +300,14 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
300
300
|
e = rb_obj_alloc(ox_element_clas);
|
301
301
|
rb_ivar_set(e, ox_at_value_id, s);
|
302
302
|
if (0 != attrs->name) {
|
303
|
-
VALUE
|
303
|
+
volatile VALUE ah = rb_hash_new();
|
304
304
|
|
305
305
|
for (; 0 != attrs->name; attrs++) {
|
306
|
-
VALUE
|
307
|
-
VALUE *slot;
|
306
|
+
volatile VALUE sym;
|
308
307
|
|
309
308
|
if (Yes == pi->options->sym_keys) {
|
309
|
+
VALUE *slot;
|
310
|
+
|
310
311
|
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, attrs->name, &slot, 0))) {
|
311
312
|
#if HAS_ENCODING_SUPPORT
|
312
313
|
if (0 != pi->options->rb_enc) {
|
@@ -329,6 +330,9 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
329
330
|
#else
|
330
331
|
sym = ID2SYM(rb_intern(attrs->name));
|
331
332
|
#endif
|
333
|
+
// Needed for Ruby 2.2 to get around the GC of symbols
|
334
|
+
// created with to_sym which is needed for encoded symbols.
|
335
|
+
rb_ary_push(ox_sym_bank, sym);
|
332
336
|
*slot = sym;
|
333
337
|
}
|
334
338
|
} else {
|
@@ -437,6 +441,9 @@ add_instruct(PInfo pi, const char *name, Attr attrs, const char *content) {
|
|
437
441
|
#else
|
438
442
|
sym = ID2SYM(rb_intern(attrs->name));
|
439
443
|
#endif
|
444
|
+
// Needed for Ruby 2.2 to get around the GC of symbols
|
445
|
+
// created with to_sym which is needed for encoded symbols.
|
446
|
+
rb_ary_push(ox_sym_bank, sym);
|
440
447
|
*slot = sym;
|
441
448
|
}
|
442
449
|
} else {
|
data/ext/ox/obj_load.c
CHANGED
@@ -82,11 +82,14 @@ name2var(const char *name, void *encoding) {
|
|
82
82
|
} else if (Qundef == (var_id = ox_cache_get(ox_attr_cache, name, &slot, 0))) {
|
83
83
|
#ifdef HAVE_RUBY_ENCODING_H
|
84
84
|
if (0 != encoding) {
|
85
|
-
VALUE rstr = rb_str_new2(name);
|
86
|
-
VALUE sym;
|
85
|
+
volatile VALUE rstr = rb_str_new2(name);
|
86
|
+
volatile VALUE sym;
|
87
87
|
|
88
88
|
rb_enc_associate(rstr, (rb_encoding*)encoding);
|
89
89
|
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
90
|
+
// Needed for Ruby 2.2 to get around the GC of symbols
|
91
|
+
// created with to_sym which is needed for encoded symbols.
|
92
|
+
rb_ary_push(ox_sym_bank, sym);
|
90
93
|
var_id = SYM2ID(sym);
|
91
94
|
} else {
|
92
95
|
var_id = rb_intern(name);
|
@@ -462,6 +465,9 @@ add_text(PInfo pi, char *text, int closed) {
|
|
462
465
|
|
463
466
|
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, text, &slot, 0))) {
|
464
467
|
sym = str2sym(text, (void*)pi->options->rb_enc);
|
468
|
+
// Needed for Ruby 2.2 to get around the GC of symbols created with
|
469
|
+
// to_sym which is needed for encoded symbols.
|
470
|
+
rb_ary_push(ox_sym_bank, sym);
|
465
471
|
*slot = sym;
|
466
472
|
}
|
467
473
|
h->obj = sym;
|
@@ -513,6 +519,9 @@ add_text(PInfo pi, char *text, int closed) {
|
|
513
519
|
from_base64(text, (uchar*)str);
|
514
520
|
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, str, &slot, 0))) {
|
515
521
|
sym = str2sym(str, (void*)pi->options->rb_enc);
|
522
|
+
// Needed for Ruby 2.2 to get around the GC of symbols created with
|
523
|
+
// to_sym which is needed for encoded symbols.
|
524
|
+
rb_ary_push(ox_sym_bank, sym);
|
516
525
|
*slot = sym;
|
517
526
|
}
|
518
527
|
h->obj = sym;
|
data/ext/ox/ox.c
CHANGED
@@ -76,6 +76,7 @@ VALUE ox_encoding_sym;
|
|
76
76
|
|
77
77
|
VALUE ox_empty_string;
|
78
78
|
VALUE ox_zero_fixnum;
|
79
|
+
VALUE ox_sym_bank; // Array
|
79
80
|
|
80
81
|
VALUE ox_arg_error_class;
|
81
82
|
VALUE ox_bag_clas;
|
@@ -995,6 +996,7 @@ void Init_ox() {
|
|
995
996
|
|
996
997
|
ox_empty_string = rb_str_new2(""); rb_gc_register_address(&ox_empty_string);
|
997
998
|
ox_zero_fixnum = INT2NUM(0); rb_gc_register_address(&ox_zero_fixnum);
|
999
|
+
ox_sym_bank = rb_ary_new(); rb_gc_register_address(&ox_sym_bank);
|
998
1000
|
|
999
1001
|
ox_document_clas = rb_const_get_at(Ox, rb_intern("Document"));
|
1000
1002
|
ox_element_clas = rb_const_get_at(Ox, rb_intern("Element"));
|
data/ext/ox/ox.h
CHANGED
data/ext/ox/sax.c
CHANGED
@@ -103,6 +103,9 @@ str2sym(SaxDrive dr, const char *str, const char **strp) {
|
|
103
103
|
|
104
104
|
rb_funcall(rstr, ox_force_encoding_id, 1, dr->encoding);
|
105
105
|
sym = rb_funcall(rstr, ox_to_sym_id, 0);
|
106
|
+
// Needed for Ruby 2.2 to get around the GC of symbols created
|
107
|
+
// with to_sym which is needed for encoded symbols.
|
108
|
+
rb_ary_push(ox_sym_bank, sym);
|
106
109
|
*slot = Qundef;
|
107
110
|
} else {
|
108
111
|
sym = ID2SYM(rb_intern(str));
|
@@ -262,12 +265,10 @@ static void
|
|
262
265
|
parse(SaxDrive dr) {
|
263
266
|
char c = skipBOM(dr);
|
264
267
|
int state = START_STATE;
|
268
|
+
Nv parent;
|
265
269
|
|
266
270
|
while ('\0' != c) {
|
267
271
|
buf_protect(&dr->buf);
|
268
|
-
if (is_white(c) && '\0' == (c = buf_next_non_white(&dr->buf))) {
|
269
|
-
break;
|
270
|
-
}
|
271
272
|
if ('<' == c) {
|
272
273
|
c = buf_get(&dr->buf);
|
273
274
|
switch (c) {
|
@@ -325,6 +326,11 @@ parse(SaxDrive dr) {
|
|
325
326
|
ox_sax_drive_error(dr, CASE_ERROR "expected CDATA all in caps");
|
326
327
|
c = read_cdata(dr);
|
327
328
|
} else {
|
329
|
+
Nv parent = stack_peek(&dr->stack);
|
330
|
+
|
331
|
+
if (0 != parent) {
|
332
|
+
parent->childCnt++;
|
333
|
+
}
|
328
334
|
ox_sax_drive_error_at(dr, WRONG_CHAR "DOCTYPE, CDATA, or comment expected", line, col);
|
329
335
|
c = read_name_token(dr);
|
330
336
|
if ('>' == c) {
|
@@ -334,6 +340,30 @@ parse(SaxDrive dr) {
|
|
334
340
|
}
|
335
341
|
break;
|
336
342
|
case '/': /* element end */
|
343
|
+
parent = stack_peek(&dr->stack);
|
344
|
+
if (0 != parent && 0 == parent->childCnt) {
|
345
|
+
VALUE args[1];
|
346
|
+
int line = dr->buf.line;
|
347
|
+
int col = dr->buf.col - 1;
|
348
|
+
|
349
|
+
args[0] = rb_str_new2("");
|
350
|
+
#if HAS_ENCODING_SUPPORT
|
351
|
+
if (0 != dr->encoding) {
|
352
|
+
rb_enc_associate(args[0], dr->encoding);
|
353
|
+
}
|
354
|
+
#elif HAS_PRIVATE_ENCODING
|
355
|
+
if (Qnil != dr->encoding) {
|
356
|
+
rb_funcall(args[0], ox_force_encoding_id, 1, dr->encoding);
|
357
|
+
}
|
358
|
+
#endif
|
359
|
+
if (dr->has.line) {
|
360
|
+
rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
|
361
|
+
}
|
362
|
+
if (dr->has.column) {
|
363
|
+
rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(col));
|
364
|
+
}
|
365
|
+
rb_funcall2(dr->handler, ox_text_id, 1, args);
|
366
|
+
}
|
337
367
|
c = read_element_end(dr);
|
338
368
|
if (0 == stack_peek(&dr->stack)) {
|
339
369
|
state = AFTER_STATE;
|
@@ -450,7 +480,7 @@ read_instruction(SaxDrive dr) {
|
|
450
480
|
dr->err = 0;
|
451
481
|
c = read_attrs(dr, c, '?', '?', is_xml, 1);
|
452
482
|
if (dr->has.attrs_done) {
|
453
|
-
|
483
|
+
rb_funcall(dr->handler, ox_attrs_done_id, 0);
|
454
484
|
}
|
455
485
|
if (dr->err) {
|
456
486
|
if (dr->has.text) {
|
@@ -557,6 +587,7 @@ read_doctype(SaxDrive dr) {
|
|
557
587
|
int line = dr->buf.line;
|
558
588
|
int col = dr->buf.col - 10;
|
559
589
|
char *s;
|
590
|
+
Nv parent = stack_peek(&dr->stack);
|
560
591
|
|
561
592
|
buf_backup(&dr->buf); /* back up to the start in case the cdata is empty */
|
562
593
|
buf_protect(&dr->buf);
|
@@ -568,6 +599,9 @@ read_doctype(SaxDrive dr) {
|
|
568
599
|
}
|
569
600
|
}
|
570
601
|
*(dr->buf.tail - 1) = '\0';
|
602
|
+
if (0 != parent) {
|
603
|
+
parent->childCnt++;
|
604
|
+
}
|
571
605
|
if (dr->has.doctype) {
|
572
606
|
VALUE args[1];
|
573
607
|
|
@@ -590,11 +624,16 @@ read_doctype(SaxDrive dr) {
|
|
590
624
|
static char
|
591
625
|
read_cdata(SaxDrive dr) {
|
592
626
|
char c;
|
627
|
+
char zero = '\0';
|
593
628
|
int end = 0;
|
594
629
|
int line = dr->buf.line;
|
595
630
|
int col = dr->buf.col - 10;
|
596
631
|
struct _CheckPt cp = CHECK_PT_INIT;
|
632
|
+
Nv parent = stack_peek(&dr->stack);
|
597
633
|
|
634
|
+
if (0 != parent) {
|
635
|
+
parent->childCnt++;
|
636
|
+
}
|
598
637
|
buf_backup(&dr->buf); /* back up to the start in case the cdata is empty */
|
599
638
|
buf_protect(&dr->buf);
|
600
639
|
while (1) {
|
@@ -624,6 +663,7 @@ read_cdata(SaxDrive dr) {
|
|
624
663
|
if (buf_checkset(&cp)) {
|
625
664
|
c = buf_checkback(&dr->buf, &cp);
|
626
665
|
ox_sax_drive_error(dr, NO_TERM "CDATA not terminated");
|
666
|
+
zero = c;
|
627
667
|
*(dr->buf.tail - 1) = '\0';
|
628
668
|
goto CB;
|
629
669
|
}
|
@@ -659,6 +699,9 @@ read_cdata(SaxDrive dr) {
|
|
659
699
|
}
|
660
700
|
rb_funcall2(dr->handler, ox_cdata_id, 1, args);
|
661
701
|
}
|
702
|
+
if ('\0' != zero) {
|
703
|
+
*(dr->buf.tail - 1) = zero;
|
704
|
+
}
|
662
705
|
dr->buf.str = 0;
|
663
706
|
|
664
707
|
return c;
|
@@ -669,6 +712,7 @@ read_cdata(SaxDrive dr) {
|
|
669
712
|
static char
|
670
713
|
read_comment(SaxDrive dr) {
|
671
714
|
char c;
|
715
|
+
char zero = '\0';
|
672
716
|
int end = 0;
|
673
717
|
int line = dr->buf.line;
|
674
718
|
int col = dr->buf.col - 4;
|
@@ -703,6 +747,7 @@ read_comment(SaxDrive dr) {
|
|
703
747
|
if (buf_checkset(&cp)) {
|
704
748
|
c = buf_checkback(&dr->buf, &cp);
|
705
749
|
ox_sax_drive_error(dr, NO_TERM "comment not terminated");
|
750
|
+
zero = c;
|
706
751
|
*(dr->buf.tail - 1) = '\0';
|
707
752
|
goto CB;
|
708
753
|
}
|
@@ -738,6 +783,9 @@ read_comment(SaxDrive dr) {
|
|
738
783
|
}
|
739
784
|
rb_funcall2(dr->handler, ox_comment_id, 1, args);
|
740
785
|
}
|
786
|
+
if ('\0' != zero) {
|
787
|
+
*(dr->buf.tail - 1) = zero;
|
788
|
+
}
|
741
789
|
dr->buf.str = 0;
|
742
790
|
|
743
791
|
return c;
|
@@ -756,10 +804,15 @@ read_element_start(SaxDrive dr) {
|
|
756
804
|
int col = dr->buf.col - 1;
|
757
805
|
Hint h = 0;
|
758
806
|
int stackless = 0;
|
807
|
+
Nv parent = stack_peek(&dr->stack);
|
808
|
+
|
759
809
|
|
760
810
|
if ('\0' == (c = read_name_token(dr))) {
|
761
811
|
return '\0';
|
762
812
|
}
|
813
|
+
if (0 != parent) {
|
814
|
+
parent->childCnt++;
|
815
|
+
}
|
763
816
|
if (dr->options.smart && 0 == dr->hints && stack_empty(&dr->stack) && 0 == strcasecmp("html", dr->buf.str)) {
|
764
817
|
dr->hints = ox_hints_html();
|
765
818
|
}
|
@@ -833,7 +886,7 @@ read_element_start(SaxDrive dr) {
|
|
833
886
|
closed = ('/' == c);
|
834
887
|
}
|
835
888
|
if (dr->has.attrs_done) {
|
836
|
-
|
889
|
+
rb_funcall(dr->handler, ox_attrs_done_id, 0);
|
837
890
|
}
|
838
891
|
if (closed) {
|
839
892
|
c = buf_next_non_white(&dr->buf);
|
@@ -950,18 +1003,46 @@ read_text(SaxDrive dr) {
|
|
950
1003
|
char c;
|
951
1004
|
int line = dr->buf.line;
|
952
1005
|
int col = dr->buf.col - 1;
|
1006
|
+
Nv parent = stack_peek(&dr->stack);
|
1007
|
+
int allWhite = 1;
|
953
1008
|
|
954
1009
|
buf_backup(&dr->buf);
|
955
1010
|
buf_protect(&dr->buf);
|
956
1011
|
while ('<' != (c = buf_get(&dr->buf))) {
|
957
|
-
|
1012
|
+
switch(c) {
|
1013
|
+
case ' ':
|
1014
|
+
case '\t':
|
1015
|
+
case '\f':
|
1016
|
+
case '\n':
|
1017
|
+
case '\r':
|
1018
|
+
break;
|
1019
|
+
case '\0':
|
1020
|
+
if (allWhite) {
|
1021
|
+
return c;
|
1022
|
+
}
|
958
1023
|
ox_sax_drive_error(dr, NO_TERM "text not terminated");
|
1024
|
+
goto END_OF_BUF;
|
959
1025
|
break;
|
960
|
-
|
1026
|
+
default:
|
1027
|
+
allWhite = 0;
|
1028
|
+
break;
|
1029
|
+
}
|
961
1030
|
}
|
1031
|
+
END_OF_BUF:
|
962
1032
|
if ('\0' != c) {
|
963
1033
|
*(dr->buf.tail - 1) = '\0';
|
964
1034
|
}
|
1035
|
+
if (allWhite) {
|
1036
|
+
int isEnd = ('/' == buf_get(&dr->buf));
|
1037
|
+
|
1038
|
+
buf_backup(&dr->buf);
|
1039
|
+
if (!isEnd || 0 == parent || 0 < parent->childCnt) {
|
1040
|
+
return c;
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
if (0 != parent) {
|
1044
|
+
parent->childCnt++;
|
1045
|
+
}
|
965
1046
|
if (dr->has.value) {
|
966
1047
|
if (dr->has.line) {
|
967
1048
|
rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(line));
|
data/ext/ox/sax_stack.h
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
typedef struct _Nv {
|
14
14
|
const char *name;
|
15
15
|
VALUE val;
|
16
|
+
int childCnt;
|
16
17
|
Hint hint;
|
17
18
|
} *Nv;
|
18
19
|
|
@@ -60,6 +61,7 @@ stack_push(NStack stack, const char *name, VALUE val, Hint hint) {
|
|
60
61
|
stack->tail->name = name;
|
61
62
|
stack->tail->val = val;
|
62
63
|
stack->tail->hint = hint;
|
64
|
+
stack->tail->childCnt = 0;
|
63
65
|
stack->tail++;
|
64
66
|
}
|
65
67
|
|
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.1.
|
4
|
+
version: 2.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-31 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
|
14
14
|
\ \nOptimized XML (Ox), as the name implies was written to provide speed
|
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|
94
94
|
rubyforge_project: ox
|
95
|
-
rubygems_version: 2.
|
95
|
+
rubygems_version: 2.4.5
|
96
96
|
signing_key:
|
97
97
|
specification_version: 4
|
98
98
|
summary: A fast XML parser and object serializer.
|