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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46587c384333cacf569a8e839535a5558571bcf4
4
- data.tar.gz: c5ef06082e351544aad217a18e485dac9e48e598
3
+ metadata.gz: 065c6a76ec5d44344dd607e266b9208f32aead7d
4
+ data.tar.gz: 242089d4a9ebe913eb825721085d1c6c8c7187f8
5
5
  SHA512:
6
- metadata.gz: 86781ade4fe9945b6d05d1c3ca5462e94f7f9947ddba0d79d29765091aeddc0f839630258a624afa899b5486235054cd6dbe6945c70af080cdedf1c7aaa06523
7
- data.tar.gz: a16bfd3f9808401f4b76bd0740ec9c5942c65698e0b3c668a36e1095209fdabbbae479d665096789948322c28e533929ce75ec1e9fe09eafb489e014343f3cd0
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.6
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
 
@@ -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 ah = rb_hash_new();
303
+ volatile VALUE ah = rb_hash_new();
304
304
 
305
305
  for (; 0 != attrs->name; attrs++) {
306
- VALUE sym;
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 {
@@ -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;
@@ -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"));
@@ -229,6 +229,7 @@ extern VALUE ox_stringio_class;
229
229
  extern VALUE ox_struct_class;
230
230
  extern VALUE ox_time_class;
231
231
  extern VALUE ox_zero_fixnum;
232
+ extern VALUE ox_sym_bank; // Array
232
233
 
233
234
  extern VALUE ox_document_clas;
234
235
  extern VALUE ox_element_clas;
@@ -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
- rb_funcall(dr->handler, ox_attrs_done_id, 0);
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
- rb_funcall(dr->handler, ox_attrs_done_id, 0);
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
- if ('\0' == c) {
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));
@@ -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
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Ox
3
3
  # Current version of the module.
4
- VERSION = '2.1.6'
4
+ VERSION = '2.1.7'
5
5
  end
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.6
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: 2014-12-31 00:00:00.000000000 Z
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.2.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.