ext/ox/dump.c in ox-1.5.1 vs ext/ox/dump.c in ox-1.5.2
- old
+ new
@@ -96,10 +96,11 @@
static void dump_value(Out out, const char *value, size_t size);
static void dump_str_value(Out out, const char *value, size_t size);
static int dump_var(ID key, VALUE value, Out out);
static void dump_num(Out out, VALUE obj);
+static void dump_date(Out out, VALUE obj);
static void dump_time_thin(Out out, VALUE obj);
static void dump_time_xsd(Out out, VALUE obj);
static int dump_hash(VALUE key, VALUE value, Out out);
static int is_xml_friendly(const u_char *str, int len);
@@ -143,12 +144,14 @@
*out->cur++ = hex_chars[d];
d = c & 0x0F;
*out->cur++ = hex_chars[d];
}
-inline static Type
+static Type
obj_class_code(VALUE obj) {
+ VALUE clas = rb_obj_class(obj);
+
switch (rb_type(obj)) {
case T_NIL: return NilClassCode;
case T_ARRAY: return ArrayCode;
case T_HASH: return HashCode;
case T_TRUE: return TrueClassCode;
@@ -160,13 +163,13 @@
{
const char *sym = rb_id2name(SYM2ID(obj));
return (is_xml_friendly((u_char*)sym, (int)strlen(sym))) ? SymbolCode : Symbol64Code;
}
- case T_DATA: return (rb_cTime == rb_obj_class(obj)) ? TimeCode : 0;
- case T_STRUCT: return (rb_cRange == rb_obj_class(obj)) ? RangeCode : StructCode;
- case T_OBJECT: return (ox_document_clas == rb_obj_class(obj) || ox_element_clas == rb_obj_class(obj)) ? RawCode : ObjectCode;
+ case T_DATA: return (rb_cTime == clas) ? TimeCode : ((ox_date_class == clas) ? DateCode : 0);
+ case T_STRUCT: return (rb_cRange == clas) ? RangeCode : StructCode;
+ case T_OBJECT: return (ox_document_clas == clas || ox_element_clas == clas) ? RawCode : ObjectCode;
case T_REGEXP: return RegexpCode;
case T_BIGNUM: return BignumCode;
#ifdef T_COMPLEX
case T_COMPLEX: return ComplexCode;
#endif
@@ -254,21 +257,17 @@
static void
grow(Out out, size_t len) {
size_t size = out->end - out->buf;
long pos = out->cur - out->buf;
- char *buf;
size *= 2;
if (size <= len * 2 + pos) {
size += len;
}
- if (0 == (buf = (char*)realloc(out->buf, size + 10))) { // 1 extra for terminator character plus extra (paranoid)
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
- }
- out->buf = buf;
- out->end = buf + size;
+ REALLOC_N(out->buf, char, size + 10); // 10 extra for terminator character plus extra (paranoid)
+ out->end = out->buf + size;
out->cur = out->buf + pos;
}
static void
dump_start(Out out, Element e) {
@@ -292,11 +291,11 @@
*out->cur++ = '<';
*out->cur++ = e->type;
if (0 < e->attr.len) {
fill_attr(out, 'a', e->attr.str, e->attr.len);
}
- if ((ObjectCode == e->type || StructCode == e->type || ClassCode == e->type) && 0 < e->clas.len) {
+ if ((ObjectCode == e->type || ExceptionCode == e->type || StructCode == e->type || ClassCode == e->type) && 0 < e->clas.len) {
fill_attr(out, 'c', e->clas.str, e->clas.len);
}
if (0 < e->id) {
char buf[32];
char *end = buf + sizeof(buf);
@@ -453,10 +452,34 @@
memcpy(out->cur, b, size);
out->cur += size;
}
static void
+dump_date(Out out, VALUE obj) {
+ char buf[64];
+ char *b = buf + sizeof(buf) - 1;
+ long jd = NUM2LONG(rb_funcall2(obj, ox_jd_id, 0, 0));
+ long size;
+
+ *b-- = '\0';
+ for (; 0 < jd; b--, jd /= 10) {
+ *b = '0' + (jd % 10);
+ }
+ b++;
+ if ('\0' == *b) {
+ b--;
+ *b = '0';
+ }
+ size = sizeof(buf) - (b - buf) - 1;
+ if (out->end - out->cur <= size) {
+ grow(out, size);
+ }
+ memcpy(out->cur, b, size);
+ out->cur += size;
+}
+
+static void
dump_time_xsd(Out out, VALUE obj) {
struct tm *tm;
time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
long usec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0));
int tzhour, tzmin;
@@ -619,28 +642,19 @@
out->w_start(out, &e);
dump_str_value(out, str, cnt);
e.indent = -1;
out->w_end(out, &e);
} else {
- char buf64[4096];
- char *b64 = buf64;
ulong size = b64_size(cnt);
+ char *b64 = ALLOCA_N(char, size + 1);
e.type = String64Code;
- if (sizeof(buf64) < size) {
- if (0 == (b64 = (char*)malloc(size + 1))) {
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
- }
- }
to_base64((u_char*)str, cnt, b64);
out->w_start(out, &e);
dump_value(out, b64, size);
e.indent = -1;
out->w_end(out, &e);
- if (buf64 != b64) {
- free(b64);
- }
}
#else
e.type = StringCode;
out->w_start(out, &e);
dump_str_value(out, str, cnt);
@@ -660,28 +674,19 @@
out->w_start(out, &e);
dump_str_value(out, sym, cnt);
e.indent = -1;
out->w_end(out, &e);
} else {
- char buf64[4096];
- char *b64 = buf64;
ulong size = b64_size(cnt);
+ char *b64 = ALLOCA_N(char, size + 1);
e.type = Symbol64Code;
- if (sizeof(buf64) < size) {
- if (0 == (b64 = (char*)malloc(size + 1))) {
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
- }
- }
to_base64((u_char*)sym, cnt, b64);
out->w_start(out, &e);
dump_value(out, b64, size);
e.indent = -1;
out->w_end(out, &e);
- if (buf64 != b64) {
- free(b64);
- }
}
#else
e.type = SymbolCode;
out->w_start(out, &e);
dump_str_value(out, sym, cnt);
@@ -699,18 +704,28 @@
e.type = TimeCode;
out->w_start(out, &e);
out->w_time(out, obj);
e.indent = -1;
out->w_end(out, &e);
- } else {
- if (StrictEffort == out->opts->effort) {
- rb_raise(rb_eNotImpError, "Failed to dump T_DATA %s\n", rb_class2name(clas));
- } else {
- e.type = NilClassCode;
- e.closed = 1;
- out->w_start(out, &e);
- }
+ } else {
+ const char *classname = rb_class2name(clas);
+
+ if (0 == strcmp("Date", classname)) {
+ e.type = DateCode;
+ out->w_start(out, &e);
+ dump_date(out, obj);
+ e.indent = -1;
+ out->w_end(out, &e);
+ } else {
+ if (StrictEffort == out->opts->effort) {
+ rb_raise(rb_eNotImpError, "Failed to dump T_DATA %s\n", classname);
+ } else {
+ e.type = NilClassCode;
+ e.closed = 1;
+ out->w_start(out, &e);
+ }
+ }
}
break;
}
case T_STRUCT:
{
@@ -777,11 +792,11 @@
dump_gen_element(obj, depth + 1, out);
out->w_end(out, &e);
} else { // Object
// use encoding as the indicator for Ruby 1.8.7 or 1.9.x
#ifdef HAVE_RUBY_ENCODING_H
- e.type = ObjectCode;
+ e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
cnt = (int)rb_ivar_count(obj);
e.closed = (0 >= cnt);
out->w_start(out, &e);
if (0 < cnt) {
unsigned int od = out->depth;
@@ -795,11 +810,11 @@
#if (defined JRUBY || defined RUBINIUS)
VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0);
#else
VALUE vars = rb_obj_instance_variables(obj);
#endif
- e.type = ObjectCode;
+ e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
cnt = (int)RARRAY_LEN(vars);
e.closed = (0 >= cnt);
out->w_start(out, &e);
if (0 < cnt) {
VALUE *np = RARRAY_PTR(vars);
@@ -837,24 +852,15 @@
#if USE_B64
if (is_xml_friendly((u_char*)s, cnt)) {
//dump_value(out, "/", 1);
dump_str_value(out, s, cnt);
} else {
- char buf64[4096];
- char *b64 = buf64;
ulong size = b64_size(cnt);
+ char *b64 = ALLOCA_N(char, size + 1);
- if (sizeof(buf64) < size) {
- if (0 == (b64 = (char*)malloc(size + 1))) {
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
- }
- }
to_base64((u_char*)s, cnt, b64);
dump_value(out, b64, size);
- if (buf64 != b64) {
- free(b64);
- }
}
#else
dump_str_value(out, s, cnt);
#endif
#if 0
@@ -1117,12 +1123,12 @@
static void
dump_obj_to_xml(VALUE obj, Options copts, Out out) {
VALUE clas = rb_obj_class(obj);
out->w_time = (Yes == copts->xsd_date) ? dump_time_xsd : dump_time_thin;
- out->buf = (char*)malloc(65336);
- out->end = out->buf + 65325; // 1 less than end plus extra for possible errors
+ out->buf = ALLOC_N(char, 65336);
+ out->end = out->buf + 65325; // 10 less than end plus extra for possible errors
out->cur = out->buf;
out->circ_cache = 0;
out->circ_cnt = 0;
out->opts = copts;
out->obj = obj;
@@ -1166,8 +1172,8 @@
}
if (size != fwrite(out.buf, 1, size, f)) {
int err = ferror(f);
rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
}
- free(out.buf);
+ xfree(out.buf);
fclose(f);
}