ox 1.5.4 → 1.5.5

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.

Files changed (61) hide show
  1. data/README.md +21 -3
  2. data/ext/ox/dump.c +64 -42
  3. data/ext/ox/extconf.rb +34 -2
  4. data/ext/ox/gen_load.c +13 -13
  5. data/ext/ox/obj_load.c +31 -28
  6. data/ext/ox/ox.c +41 -31
  7. data/ext/ox/ox.h +20 -13
  8. data/ext/ox/parse.c +1 -0
  9. data/ext/ox/sax.c +323 -26
  10. data/lib/ox.rb +1 -2
  11. data/lib/ox/element.rb +1 -1
  12. data/lib/ox/sax.rb +24 -11
  13. data/lib/ox/version.rb +1 -1
  14. metadata +4 -50
  15. data/test/Sample.graffle +0 -2318
  16. data/test/bench.rb +0 -53
  17. data/test/bug1.rb +0 -24
  18. data/test/bug2.rb +0 -38
  19. data/test/bug3.rb +0 -21
  20. data/test/cache16_test.rb +0 -17
  21. data/test/cache8_test.rb +0 -17
  22. data/test/cache_test.rb +0 -17
  23. data/test/files.rb +0 -29
  24. data/test/func.rb +0 -652
  25. data/test/gen_sample.rb +0 -22
  26. data/test/obj_sample.rb +0 -19
  27. data/test/ox/change.rb +0 -16
  28. data/test/ox/dir.rb +0 -21
  29. data/test/ox/doc.rb +0 -39
  30. data/test/ox/file.rb +0 -33
  31. data/test/ox/group.rb +0 -18
  32. data/test/ox/hasprops.rb +0 -18
  33. data/test/ox/layer.rb +0 -14
  34. data/test/ox/line.rb +0 -22
  35. data/test/ox/oval.rb +0 -12
  36. data/test/ox/rect.rb +0 -12
  37. data/test/ox/shape.rb +0 -37
  38. data/test/ox/text.rb +0 -23
  39. data/test/parse_cmp.rb +0 -261
  40. data/test/perf.rb +0 -91
  41. data/test/perf_gen.rb +0 -237
  42. data/test/perf_mars.rb +0 -114
  43. data/test/perf_obj.rb +0 -124
  44. data/test/perf_pod.rb +0 -88
  45. data/test/perf_sax.rb +0 -233
  46. data/test/perf_write.rb +0 -80
  47. data/test/sample.rb +0 -55
  48. data/test/sample/change.rb +0 -14
  49. data/test/sample/dir.rb +0 -19
  50. data/test/sample/doc.rb +0 -36
  51. data/test/sample/file.rb +0 -48
  52. data/test/sample/group.rb +0 -16
  53. data/test/sample/hasprops.rb +0 -16
  54. data/test/sample/layer.rb +0 -12
  55. data/test/sample/line.rb +0 -20
  56. data/test/sample/oval.rb +0 -10
  57. data/test/sample/rect.rb +0 -10
  58. data/test/sample/shape.rb +0 -35
  59. data/test/sample/text.rb +0 -20
  60. data/test/sax_test.rb +0 -468
  61. data/test/test.rb +0 -70
data/README.md CHANGED
@@ -30,11 +30,29 @@ A fast XML parser and Object marshaller as a Ruby gem.
30
30
 
31
31
  ## <a name="release">Release Notes</a>
32
32
 
33
- ### Release 1.5.4
33
+ ### Release 1.5.5
34
34
 
35
- - Worked around bug in rb_protect in ruby 1.9.x and OS X 10.6.8 that caused ignored exceptions to be raised on program exit.
35
+ - Fixed bug in special character encoding to remove the double ampersands.
36
36
 
37
- - Fixed a parse bug that did not accept &nn; sequences.
37
+ - Fixed bug that did not dump XSD times correctly.
38
+
39
+ - Fixed bug in the prolog parsing.
40
+
41
+ - Improved the speed of time parsing and dumping.
42
+
43
+ - Increased the time resolution for Rubies that support nanoseconds.
44
+
45
+ - Cleaned up compile flags.
46
+
47
+ - All tests pass with all supported Rubies.
48
+
49
+ - Added value() callback to the SAX parser which allows deferred value parsing and typing to improve performance.
50
+
51
+ - Added attr_value() callback to the SAX parser which allows deferred value parsing and typing to improve performance with attributes.
52
+
53
+ - Added an example that demonstrates using several parsing techniques with different parsers. The example is in the test/weather directory.
54
+
55
+ - The SAX parser was optimized slightly for StringIO input.
38
56
 
39
57
  ## <a name="description">Description</a>
40
58
 
data/ext/ox/dump.c CHANGED
@@ -34,12 +34,6 @@
34
34
  #include <stdio.h>
35
35
  #include <string.h>
36
36
 
37
- #include "ruby.h"
38
- #ifdef HAVE_RUBY_ENCODING_H
39
- #include "ruby/st.h"
40
- #else
41
- #include "st.h"
42
- #endif
43
37
  #include "base64.h"
44
38
  #include "cache8.h"
45
39
  #include "ox.h"
@@ -298,7 +292,7 @@ dump_start(Out out, Element e) {
298
292
  }
299
293
  if (0 < e->id) {
300
294
  char buf[32];
301
- char *end = buf + sizeof(buf);
295
+ char *end = buf + sizeof(buf) - 1;
302
296
  const char *s = ulong2str(e->id, end);
303
297
 
304
298
  fill_attr(out, 'i', s, end - s);
@@ -380,7 +374,6 @@ dump_str_value(Out out, const char *value, size_t size) {
380
374
  *out->cur++ = 't';
381
375
  break;
382
376
  default:
383
- *out->cur++ = '&';
384
377
  *out->cur++ = '#';
385
378
  *out->cur++ = 'x';
386
379
  *out->cur++ = '0';
@@ -429,16 +422,26 @@ dump_num(Out out, VALUE obj) {
429
422
 
430
423
  static void
431
424
  dump_time_thin(Out out, VALUE obj) {
432
- char buf[64];
433
- char *b = buf + sizeof(buf) - 1;
434
- time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
435
- long usec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0));
436
- char *dot = b - 7;
437
- long size;
425
+ char buf[64];
426
+ char *b = buf + sizeof(buf) - 1;
427
+ #if HAS_RB_TIME_TIMESPEC
428
+ struct timespec ts = rb_time_timespec(obj);
429
+ time_t sec = ts.tv_sec;
430
+ long nsec = ts.tv_nsec;
431
+ #else
432
+ time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
433
+ #if HAS_NANO_TIME
434
+ long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
435
+ #else
436
+ long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
437
+ #endif
438
+ #endif
439
+ char *dot = b - 10;
440
+ long size;
438
441
 
439
442
  *b-- = '\0';
440
- for (; dot < b; b--, usec /= 10) {
441
- *b = '0' + (usec % 10);
443
+ for (; dot < b; b--, nsec /= 10) {
444
+ *b = '0' + (nsec % 10);
442
445
  }
443
446
  *b-- = '.';
444
447
  for (; 0 < sec; b--, sec /= 10) {
@@ -479,11 +482,21 @@ dump_date(Out out, VALUE obj) {
479
482
 
480
483
  static void
481
484
  dump_time_xsd(Out out, VALUE obj) {
482
- struct tm *tm;
483
- time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
484
- long usec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0));
485
- int tzhour, tzmin;
486
- char tzsign = '+';
485
+ struct tm *tm;
486
+ #if HAS_RB_TIME_TIMESPEC
487
+ struct timespec ts = rb_time_timespec(obj);
488
+ time_t sec = ts.tv_sec;
489
+ long nsec = ts.tv_nsec;
490
+ #else
491
+ time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
492
+ #if HAS_NANO_TIME
493
+ long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
494
+ #else
495
+ long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
496
+ #endif
497
+ #endif
498
+ int tzhour, tzmin;
499
+ char tzsign = '+';
487
500
 
488
501
  if (out->end - out->cur <= 33) {
489
502
  grow(out, 33);
@@ -498,10 +511,11 @@ dump_time_xsd(Out out, VALUE obj) {
498
511
  tzhour = (int)(tm->tm_gmtoff / 3600);
499
512
  tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60);
500
513
  }
501
- sprintf(out->cur, "%04d-%02d-%02dT%02d:%02d:%02d.%06ld%c%02d:%02d",
502
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
503
- tm->tm_hour, tm->tm_min, tm->tm_sec, usec,
504
- tzsign, tzhour, tzmin);
514
+ // TBD replace with more efficient printer
515
+ out->cur += sprintf(out->cur, "%04d-%02d-%02dT%02d:%02d:%02d.%06ld%c%02d:%02d",
516
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
517
+ tm->tm_hour, tm->tm_min, tm->tm_sec, nsec / 1000,
518
+ tzsign, tzhour, tzmin);
505
519
  }
506
520
 
507
521
  static void
@@ -621,7 +635,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
621
635
  break;
622
636
  case T_FLOAT:
623
637
  e.type = FloatCode;
624
- cnt = sprintf(value_buf, "%0.16g", RFLOAT_VALUE(obj)); // used sprintf due to bug in snprintf
638
+ cnt = sprintf(value_buf, "%0.16g", rb_num2dbl(obj)); // used sprintf due to bug in snprintf
625
639
  out->w_start(out, &e);
626
640
  dump_value(out, value_buf, cnt);
627
641
  e.indent = -1;
@@ -729,11 +743,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
729
743
  }
730
744
  case T_STRUCT:
731
745
  {
732
- #ifdef NO_RSTRUCT
733
- e.type = NilClassCode;
734
- e.closed = 1;
735
- out->w_start(out, &e);
736
- #else
746
+ #if HAS_RSTRUCT
737
747
  VALUE clas;
738
748
 
739
749
  if (0 != out->circ_cache && check_circular(out, obj, &e)) {
@@ -768,6 +778,10 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
768
778
  }
769
779
  out->w_end(out, &e);
770
780
  }
781
+ #else
782
+ e.type = NilClassCode;
783
+ e.closed = 1;
784
+ out->w_start(out, &e);
771
785
  #endif
772
786
  break;
773
787
  }
@@ -792,8 +806,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
792
806
  dump_gen_element(obj, depth + 1, out);
793
807
  out->w_end(out, &e);
794
808
  } else { // Object
795
- // use encoding as the indicator for Ruby 1.8.7 or 1.9.x
796
- #ifdef HAVE_RUBY_ENCODING_H
809
+ #if HAS_IVAR_HELPERS
797
810
  e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
798
811
  cnt = (int)rb_ivar_count(obj);
799
812
  e.closed = (0 >= cnt);
@@ -807,11 +820,10 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
807
820
  out->w_end(out, &e);
808
821
  }
809
822
  #else
810
- #if (defined JRUBY || defined RUBINIUS)
823
+ //VALUE vars = rb_obj_instance_variables(obj);
824
+ //#else
811
825
  VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0);
812
- #else
813
- VALUE vars = rb_obj_instance_variables(obj);
814
- #endif
826
+ //#endif
815
827
  e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
816
828
  cnt = (int)RARRAY_LEN(vars);
817
829
  e.closed = (0 >= cnt);
@@ -890,21 +902,31 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
890
902
  out->w_end(out, &e);
891
903
  break;
892
904
  }
893
- #if (defined T_COMPLEX && defined RCOMPLEX)
905
+ #ifdef T_COMPLEX
894
906
  case T_COMPLEX:
895
907
  e.type = ComplexCode;
896
908
  out->w_start(out, &e);
909
+ #ifdef RCOMPLEX
897
910
  dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out);
898
911
  dump_obj(0, RCOMPLEX(obj)->imag, depth + 1, out);
912
+ #else
913
+ dump_obj(0, rb_funcall2(obj, rb_intern("real"), 0, 0), depth + 1, out);
914
+ dump_obj(0, rb_funcall2(obj, rb_intern("imag"), 0, 0), depth + 1, out);
915
+ #endif
899
916
  out->w_end(out, &e);
900
917
  break;
901
918
  #endif
902
- #if (defined T_RATIONAL && defined RRATIONAL)
919
+ #ifdef T_RATIONAL
903
920
  case T_RATIONAL:
904
921
  e.type = RationalCode;
905
922
  out->w_start(out, &e);
923
+ #ifdef RRATIONAL
906
924
  dump_obj(0, RRATIONAL(obj)->num, depth + 1, out);
907
925
  dump_obj(0, RRATIONAL(obj)->den, depth + 1, out);
926
+ #else
927
+ dump_obj(0, rb_funcall2(obj, rb_intern("numerator"), 0, 0), depth + 1, out);
928
+ dump_obj(0, rb_funcall2(obj, rb_intern("denominator"), 0, 0), depth + 1, out);
929
+ #endif
908
930
  out->w_end(out, &e);
909
931
  break;
910
932
  #endif
@@ -920,7 +942,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
920
942
  default:
921
943
  if (StrictEffort == out->opts->effort) {
922
944
  rb_raise(rb_eNotImpError, "Failed to dump %s Object (%02x)\n",
923
- rb_class2name(rb_obj_class(obj)), rb_type(obj));
945
+ rb_obj_classname(obj), rb_type(obj));
924
946
  } else {
925
947
  e.type = NilClassCode;
926
948
  e.closed = 1;
@@ -991,7 +1013,7 @@ dump_gen_doc(VALUE obj, unsigned int depth, Out out) {
991
1013
 
992
1014
  static void
993
1015
  dump_gen_element(VALUE obj, unsigned int depth, Out out) {
994
- VALUE rname = rb_attr_get(obj, ox_value_id);
1016
+ VALUE rname = rb_attr_get(obj, ox_at_value_id);
995
1017
  VALUE attrs = rb_attr_get(obj, ox_attributes_id);
996
1018
  VALUE nodes = rb_attr_get(obj, ox_nodes_id);
997
1019
  const char *name = StringValuePtr(rname);
@@ -1091,7 +1113,7 @@ static void
1091
1113
  dump_gen_val_node(VALUE obj, unsigned int depth,
1092
1114
  const char *pre, size_t plen,
1093
1115
  const char *suf, size_t slen, Out out) {
1094
- VALUE v = rb_attr_get(obj, ox_value_id);
1116
+ VALUE v = rb_attr_get(obj, ox_at_value_id);
1095
1117
  const char *val;
1096
1118
  size_t vlen;
1097
1119
  size_t size;
data/ext/ox/extconf.rb CHANGED
@@ -1,7 +1,39 @@
1
1
  require 'mkmf'
2
2
 
3
- $CPPFLAGS += ' -Wall'
4
- #puts "*** $CPPFLAGS: #{$CPPFLAGS}"
5
3
  extension_name = 'ox'
6
4
  dir_config(extension_name)
5
+
6
+ parts = RUBY_DESCRIPTION.split(' ')
7
+ type = parts[0]
8
+ type = 'ree' if 'ruby' == type && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
9
+ version = RUBY_VERSION.split('.')
10
+ puts ">>>>> Creating Makefile for #{type} version #{RUBY_VERSION} <<<<<"
11
+
12
+ dflags = {
13
+ 'RUBY_TYPE' => type,
14
+ (type.upcase + '_RUBY') => nil,
15
+ 'RUBY_VERSION' => RUBY_VERSION,
16
+ 'RUBY_VERSION_MAJOR' => version[0],
17
+ 'RUBY_VERSION_MINOR' => version[1],
18
+ 'RUBY_VERSION_MICRO' => version[2],
19
+ 'HAS_RB_TIME_TIMESPEC' => ('ruby' == type && '1.9.3' == RUBY_VERSION) ? 1 : 0,
20
+ 'HAS_ENCODING_SUPPORT' => (('ruby' == type || 'rubinius' == type) && '1' == version[0] && '9' == version[1]) ? 1 : 0,
21
+ 'HAS_NANO_TIME' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
22
+ 'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type) ? 1 : 0,
23
+ 'HAS_IVAR_HELPERS' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
24
+ 'HAS_PROC_WITH_BLOCK' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
25
+ 'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
26
+ }
27
+
28
+ dflags.each do |k,v|
29
+ if v.nil?
30
+ $CPPFLAGS += " -D#{k}"
31
+ else
32
+ $CPPFLAGS += " -D#{k}=#{v}"
33
+ end
34
+ end
35
+ $CPPFLAGS += ' -Wall'
36
+ #puts "*** $CPPFLAGS: #{$CPPFLAGS}"
7
37
  create_makefile(extension_name)
38
+
39
+ %x{make clean}
data/ext/ox/gen_load.c CHANGED
@@ -114,7 +114,7 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
114
114
  doc = rb_obj_alloc(ox_document_clas);
115
115
  ah = rb_hash_new();
116
116
  for (; 0 != attrs->name; attrs++) {
117
- #ifdef HAVE_RUBY_ENCODING_H
117
+ #if HAS_ENCODING_SUPPORT
118
118
  if (0 != pi->encoding) {
119
119
  VALUE rstr = rb_str_new2(attrs->name);
120
120
 
@@ -127,7 +127,7 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
127
127
  sym = ID2SYM(rb_intern(attrs->name));
128
128
  #endif
129
129
  rb_hash_aset(ah, sym, rb_str_new2(attrs->value));
130
- #ifdef HAVE_RUBY_ENCODING_H
130
+ #if HAS_ENCODING_SUPPORT
131
131
  if (0 == strcmp("encoding", attrs->name)) {
132
132
  pi->encoding = rb_enc_find(attrs->value);
133
133
  }
@@ -198,12 +198,12 @@ add_doctype(PInfo pi, const char *docType) {
198
198
  VALUE n = rb_obj_alloc(ox_doctype_clas);
199
199
  VALUE s = rb_str_new2(docType);
200
200
 
201
- #ifdef HAVE_RUBY_ENCODING_H
201
+ #if HAS_ENCODING_SUPPORT
202
202
  if (0 != pi->encoding) {
203
203
  rb_enc_associate(s, pi->encoding);
204
204
  }
205
205
  #endif
206
- rb_ivar_set(n, ox_value_id, s);
206
+ rb_ivar_set(n, ox_at_value_id, s);
207
207
  if (0 == pi->h) { // top level object
208
208
  create_doc(pi);
209
209
  }
@@ -215,12 +215,12 @@ add_comment(PInfo pi, const char *comment) {
215
215
  VALUE n = rb_obj_alloc(ox_comment_clas);
216
216
  VALUE s = rb_str_new2(comment);
217
217
 
218
- #ifdef HAVE_RUBY_ENCODING_H
218
+ #if HAS_ENCODING_SUPPORT
219
219
  if (0 != pi->encoding) {
220
220
  rb_enc_associate(s, pi->encoding);
221
221
  }
222
222
  #endif
223
- rb_ivar_set(n, ox_value_id, s);
223
+ rb_ivar_set(n, ox_at_value_id, s);
224
224
  if (0 == pi->h) { // top level object
225
225
  create_doc(pi);
226
226
  }
@@ -232,12 +232,12 @@ add_cdata(PInfo pi, const char *cdata, size_t len) {
232
232
  VALUE n = rb_obj_alloc(ox_cdata_clas);
233
233
  VALUE s = rb_str_new2(cdata);
234
234
 
235
- #ifdef HAVE_RUBY_ENCODING_H
235
+ #if HAS_ENCODING_SUPPORT
236
236
  if (0 != pi->encoding) {
237
237
  rb_enc_associate(s, pi->encoding);
238
238
  }
239
239
  #endif
240
- rb_ivar_set(n, ox_value_id, s);
240
+ rb_ivar_set(n, ox_at_value_id, s);
241
241
  if (0 == pi->h) { // top level object
242
242
  create_doc(pi);
243
243
  }
@@ -248,7 +248,7 @@ static void
248
248
  add_text(PInfo pi, char *text, int closed) {
249
249
  VALUE s = rb_str_new2(text);
250
250
 
251
- #ifdef HAVE_RUBY_ENCODING_H
251
+ #if HAS_ENCODING_SUPPORT
252
252
  if (0 != pi->encoding) {
253
253
  rb_enc_associate(s, pi->encoding);
254
254
  }
@@ -264,13 +264,13 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
264
264
  VALUE e;
265
265
  VALUE s = rb_str_new2(ename);
266
266
 
267
- #ifdef HAVE_RUBY_ENCODING_H
267
+ #if HAS_ENCODING_SUPPORT
268
268
  if (0 != pi->encoding) {
269
269
  rb_enc_associate(s, pi->encoding);
270
270
  }
271
271
  #endif
272
272
  e = rb_obj_alloc(ox_element_clas);
273
- rb_ivar_set(e, ox_value_id, s);
273
+ rb_ivar_set(e, ox_at_value_id, s);
274
274
  if (0 != attrs->name) {
275
275
  VALUE ah = rb_hash_new();
276
276
 
@@ -279,7 +279,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
279
279
  VALUE *slot;
280
280
 
281
281
  if (Qundef == (sym = ox_cache_get(ox_symbol_cache, attrs->name, &slot))) {
282
- #ifdef HAVE_RUBY_ENCODING_H
282
+ #if HAS_ENCODING_SUPPORT
283
283
  if (0 != pi->encoding) {
284
284
  VALUE rstr = rb_str_new2(attrs->name);
285
285
 
@@ -294,7 +294,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
294
294
  *slot = sym;
295
295
  }
296
296
  s = rb_str_new2(attrs->value);
297
- #ifdef HAVE_RUBY_ENCODING_H
297
+ #if HAS_ENCODING_SUPPORT
298
298
  if (0 != pi->encoding) {
299
299
  rb_enc_associate(s, pi->encoding);
300
300
  }
data/ext/ox/obj_load.c CHANGED
@@ -164,7 +164,7 @@ classname2obj(const char *name, PInfo pi, VALUE base_class) {
164
164
  }
165
165
  }
166
166
 
167
- #ifndef NO_RSTRUCT
167
+ #if HAS_RSTRUCT
168
168
  inline static VALUE
169
169
  structname2obj(const char *name) {
170
170
  VALUE ost;
@@ -181,7 +181,7 @@ structname2obj(const char *name) {
181
181
  }
182
182
  ost = rb_const_get(ox_struct_class, rb_intern(s));
183
183
  // use encoding as the indicator for Ruby 1.8.7 or 1.9.x
184
- #ifdef HAVE_RUBY_ENCODING_H
184
+ #if HAS_ENCODING_SUPPORT
185
185
  return rb_struct_alloc_noinit(ost);
186
186
  #else
187
187
  return rb_struct_new(ost);
@@ -273,7 +273,7 @@ get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
273
273
  return Qundef;
274
274
  }
275
275
 
276
- #ifndef NO_RSTRUCT
276
+ #if HAS_RSTRUCT
277
277
  static VALUE
278
278
  get_struct_from_attrs(Attr a) {
279
279
  for (; 0 != a->name; a++) {
@@ -380,7 +380,7 @@ parse_regexp(const char *text) {
380
380
  int options = 0;
381
381
 
382
382
  te = text + strlen(text) - 1;
383
- #ifdef HAVE_RUBY_ENCODING_H
383
+ #if HAS_ENCODING_SUPPORT
384
384
  for (; text < te && '/' != *te; te--) {
385
385
  switch (*te) {
386
386
  case 'i': options |= ONIG_OPTION_IGNORECASE; break;
@@ -396,7 +396,7 @@ parse_regexp(const char *text) {
396
396
  static void
397
397
  instruct(PInfo pi, const char *target, Attr attrs) {
398
398
  if (0 == strcmp("xml", target)) {
399
- #ifdef HAVE_RUBY_ENCODING_H
399
+ #if HAS_ENCODING_SUPPORT
400
400
  for (; 0 != attrs->name; attrs++) {
401
401
  if (0 == strcmp("encoding", attrs->name)) {
402
402
  pi->encoding = rb_enc_find(attrs->value);
@@ -421,7 +421,7 @@ add_text(PInfo pi, char *text, int closed) {
421
421
  case NoCode:
422
422
  case StringCode:
423
423
  pi->h->obj = rb_str_new2(text);
424
- #ifdef HAVE_RUBY_ENCODING_H
424
+ #if HAS_ENCODING_SUPPORT
425
425
  if (0 != pi->encoding) {
426
426
  rb_enc_associate(pi->h->obj, pi->encoding);
427
427
  }
@@ -488,7 +488,7 @@ add_text(PInfo pi, char *text, int closed) {
488
488
 
489
489
  from_base64(text, (u_char*)str);
490
490
  v = rb_str_new(str, str_size);
491
- #ifdef HAVE_RUBY_ENCODING_H
491
+ #if HAS_ENCODING_SUPPORT
492
492
  if (0 != pi->encoding) {
493
493
  rb_enc_associate(v, pi->encoding);
494
494
  }
@@ -648,13 +648,13 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
648
648
  }
649
649
  break;
650
650
  case StructCode:
651
- #ifdef NO_RSTRUCT
652
- raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
653
- #else
651
+ #if HAS_RSTRUCT
654
652
  h->obj = get_struct_from_attrs(attrs);
655
653
  if (0 != pi->circ_array) {
656
654
  circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
657
655
  }
656
+ #else
657
+ raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
658
658
  #endif
659
659
  break;
660
660
  case ClassCode:
@@ -714,10 +714,10 @@ end_element(PInfo pi, const char *ename) {
714
714
  }
715
715
  break;
716
716
  case StructCode:
717
- #ifdef NO_RSTRUCT
718
- raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
719
- #else
717
+ #if HAS_RSTRUCT
720
718
  rb_struct_aset(pi->h->obj, h->var, h->obj);
719
+ #else
720
+ raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
721
721
  #endif
722
722
  break;
723
723
  case HashCode:
@@ -725,9 +725,7 @@ end_element(PInfo pi, const char *ename) {
725
725
  pi->h++;
726
726
  break;
727
727
  case RangeCode:
728
- #ifdef NO_RSTRUCT
729
- raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
730
- #else
728
+ #if HAS_RSTRUCT
731
729
  if (ox_beg_id == h->var) {
732
730
  RSTRUCT_PTR(pi->h->obj)[0] = h->obj;
733
731
  } else if (ox_end_id == h->var) {
@@ -737,6 +735,8 @@ end_element(PInfo pi, const char *ename) {
737
735
  } else {
738
736
  raise_error("Invalid range attribute", pi->str, pi->s);
739
737
  }
738
+ #else
739
+ raise_error("Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
740
740
  #endif
741
741
  break;
742
742
  case KeyCode:
@@ -759,7 +759,11 @@ end_element(PInfo pi, const char *ename) {
759
759
  if (Qundef == pi->h->obj) {
760
760
  pi->h->obj = h->obj;
761
761
  } else {
762
+ #ifdef RUBINIUS_RUBY
763
+ pi->h->obj = rb_Rational(pi->h->obj, h->obj);
764
+ #else
762
765
  pi->h->obj = rb_rational_new(pi->h->obj, h->obj);
766
+ #endif
763
767
  }
764
768
  #else
765
769
  raise_error("Rational Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
@@ -782,7 +786,6 @@ end_element(PInfo pi, const char *ename) {
782
786
 
783
787
  static VALUE
784
788
  parse_double_time(const char *text, VALUE clas) {
785
- VALUE args[2];
786
789
  long v = 0;
787
790
  long v2 = 0;
788
791
  const char *dot = 0;
@@ -803,13 +806,14 @@ parse_double_time(const char *text, VALUE clas) {
803
806
  }
804
807
  v2 = 10 * v2 + (long)(c - '0');
805
808
  }
806
- for (; text - dot <= 6; text++) {
809
+ for (; text - dot <= 9; text++) {
807
810
  v2 *= 10;
808
811
  }
809
- args[0] = LONG2NUM(v);
810
- args[1] = LONG2NUM(v2);
811
-
812
- return rb_funcall2(clas, ox_at_id, 2, args);
812
+ #if HAS_NANO_TIME
813
+ return rb_time_nano_new(v, v2);
814
+ #else
815
+ return rb_time_new(v, v2 / 1000);
816
+ #endif
813
817
  }
814
818
 
815
819
  typedef struct _Tp {
@@ -820,7 +824,6 @@ typedef struct _Tp {
820
824
 
821
825
  static VALUE
822
826
  parse_xsd_time(const char *text, VALUE clas) {
823
- VALUE args[2];
824
827
  long cargs[10];
825
828
  long *cp = cargs;
826
829
  long v;
@@ -862,11 +865,11 @@ parse_xsd_time(const char *text, VALUE clas) {
862
865
  tm.tm_hour = (int)cargs[3];
863
866
  tm.tm_min = (int)cargs[4];
864
867
  tm.tm_sec = (int)cargs[5];
865
-
866
- args[0] = LONG2NUM(mktime(&tm));
867
- args[1] = LONG2NUM(cargs[6]);
868
-
869
- return rb_funcall2(clas, ox_at_id, 2, args);
868
+ #if HAS_NANO_TIME
869
+ return rb_time_nano_new(mktime(&tm), cargs[6]);
870
+ #else
871
+ return rb_time_new(mktime(&tm), cargs[6] / 1000);
872
+ #endif
870
873
  }
871
874
 
872
875
  // debug functions