ext/ox/dump.c in ox-2.14.14 vs ext/ox/dump.c in ox-2.14.15

- old
+ new

@@ -1,1227 +1,1203 @@ /* dump.c * Copyright (c) 2011, Peter Ohler * All rights reserved. */ -#include <stdlib.h> #include <errno.h> -#include <time.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <time.h> #include "base64.h" #include "cache8.h" #include "ox.h" -#define USE_B64 0 +#define USE_B64 0 #define MAX_DEPTH 1000 -typedef unsigned long ulong; +typedef unsigned long ulong; typedef struct _str { - const char *str; - size_t len; + const char *str; + size_t len; } *Str; typedef struct _element { - struct _str clas; - struct _str attr; - unsigned long id; - int indent; /* < 0 indicates no \n */ - int closed; - char type; + struct _str clas; + struct _str attr; + unsigned long id; + int indent; /* < 0 indicates no \n */ + int closed; + char type; } *Element; typedef struct _out { - void (*w_start)(struct _out *out, Element e); - void (*w_end)(struct _out *out, Element e); - void (*w_time)(struct _out *out, VALUE obj); - char *buf; - char *end; - char *cur; - Cache8 circ_cache; - unsigned long circ_cnt; - int indent; - int depth; /* used by dumpHash */ - Options opts; - VALUE obj; + void (*w_start)(struct _out *out, Element e); + void (*w_end)(struct _out *out, Element e); + void (*w_time)(struct _out *out, VALUE obj); + char *buf; + char *end; + char *cur; + Cache8 circ_cache; + unsigned long circ_cnt; + int indent; + int depth; /* used by dumpHash */ + Options opts; + VALUE obj; } *Out; -static void dump_obj_to_xml(VALUE obj, Options copts, Out out); +static void dump_obj_to_xml(VALUE obj, Options copts, Out out); -static void dump_first_obj(VALUE obj, Out out); -static void dump_obj(ID aid, VALUE obj, int depth, Out out); -static void dump_gen_doc(VALUE obj, int depth, Out out); -static void dump_gen_element(VALUE obj, int depth, Out out); -static void dump_gen_instruct(VALUE obj, int depth, Out out); -static int dump_gen_attr(VALUE key, VALUE value, VALUE ov); -static int dump_gen_nodes(VALUE obj, int depth, Out out); -static void dump_gen_val_node(VALUE obj, int depth, - const char *pre, size_t plen, - const char *suf, size_t slen, Out out); +static void dump_first_obj(VALUE obj, Out out); +static void dump_obj(ID aid, VALUE obj, int depth, Out out); +static void dump_gen_doc(VALUE obj, int depth, Out out); +static void dump_gen_element(VALUE obj, int depth, Out out); +static void dump_gen_instruct(VALUE obj, int depth, Out out); +static int dump_gen_attr(VALUE key, VALUE value, VALUE ov); +static int dump_gen_nodes(VALUE obj, int depth, Out out); +static void +dump_gen_val_node(VALUE obj, int depth, const char *pre, size_t plen, const char *suf, size_t slen, Out out); -static void dump_start(Out out, Element e); -static void dump_end(Out out, Element e); +static void dump_start(Out out, Element e); +static void dump_end(Out out, Element e); -static void grow(Out out, size_t len); +static void grow(Out out, size_t len); -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, const char *table); -static int dump_var(ID key, VALUE value, VALUE ov); -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, VALUE ov); +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, const char *table); +static int dump_var(ID key, VALUE value, VALUE ov); +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, VALUE ov); -static int is_xml_friendly(const uchar *str, int len, const char *table); +static int is_xml_friendly(const uchar *str, int len, const char *table); -static const char hex_chars[17] = "0123456789abcdef"; +static const char hex_chars[17] = "0123456789abcdef"; // The : character is equivalent to 10. Used for replacement characters up to 10 // characters long such as '&#x10FFFF;'. -static const char xml_friendly_chars[257] = "\ +static const char xml_friendly_chars[257] = "\ :::::::::11::1::::::::::::::::::\ 11611156111111111111111111114141\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111"; -static const char xml_quote_chars[257] = "\ +static const char xml_quote_chars[257] = "\ :::::::::11::1::::::::::::::::::\ 11611151111111111111111111114141\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111"; -static const char xml_element_chars[257] = "\ +static const char xml_element_chars[257] = "\ :::::::::11::1::::::::::::::::::\ 11111151111111111111111111114141\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111\ 11111111111111111111111111111111"; -inline static int -is_xml_friendly(const uchar *str, int len, const char *table) { +inline static int is_xml_friendly(const uchar *str, int len, const char *table) { for (; 0 < len; str++, len--) { - if ('1' != table[*str]) { - return 0; - } + if ('1' != table[*str]) { + return 0; + } } return 1; } -inline static size_t -xml_str_len(const uchar *str, size_t len, const char *table) { - size_t size = 0; +inline static size_t xml_str_len(const uchar *str, size_t len, const char *table) { + size_t size = 0; for (; 0 < len; str++, len--) { - size += xml_friendly_chars[*str]; + size += xml_friendly_chars[*str]; } return size - len * (size_t)'0'; } -inline static void -dump_hex(uchar c, Out out) { - uchar d = (c >> 4) & 0x0F; +inline static void dump_hex(uchar c, Out out) { + uchar d = (c >> 4) & 0x0F; *out->cur++ = hex_chars[d]; - d = c & 0x0F; + d = c & 0x0F; *out->cur++ = hex_chars[d]; } -static Type -obj_class_code(VALUE obj) { - VALUE clas = rb_obj_class(obj); +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; - case T_FALSE: return FalseClassCode; - case T_FIXNUM: return FixnumCode; - case T_FLOAT: return FloatCode; - case T_STRING: return (is_xml_friendly((uchar*)StringValuePtr(obj), (int)RSTRING_LEN(obj), xml_element_chars)) ? StringCode : String64Code; - case T_SYMBOL: - { - const char *sym = rb_id2name(SYM2ID(obj)); + case T_NIL: return NilClassCode; + case T_ARRAY: return ArrayCode; + case T_HASH: return HashCode; + case T_TRUE: return TrueClassCode; + case T_FALSE: return FalseClassCode; + case T_FIXNUM: return FixnumCode; + case T_FLOAT: return FloatCode; + case T_STRING: + return (is_xml_friendly((uchar *)StringValuePtr(obj), (int)RSTRING_LEN(obj), xml_element_chars)) ? StringCode + : String64Code; + case T_SYMBOL: { + const char *sym = rb_id2name(SYM2ID(obj)); - return (is_xml_friendly((uchar*)sym, (int)strlen(sym), xml_element_chars)) ? SymbolCode : Symbol64Code; + return (is_xml_friendly((uchar *)sym, (int)strlen(sym), xml_element_chars)) ? SymbolCode : Symbol64Code; } - 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; + 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; + case T_COMPLEX: return ComplexCode; #endif #ifdef T_RATIONAL - case T_RATIONAL: return RationalCode; + case T_RATIONAL: return RationalCode; #endif - case T_CLASS: return ClassCode; - default: return 0; + case T_CLASS: return ClassCode; + default: return 0; } } -inline static void -fill_indent(Out out, int cnt) { +inline static void fill_indent(Out out, int cnt) { if (0 <= cnt) { - *out->cur++ = '\n'; - if (0 < out->opts->margin_len) { - memcpy(out->cur, out->opts->margin, out->opts->margin_len); - out->cur += out->opts->margin_len; - } - for (; 0 < cnt; cnt--) { - *out->cur++ = ' '; - } + *out->cur++ = '\n'; + if (0 < out->opts->margin_len) { + memcpy(out->cur, out->opts->margin, out->opts->margin_len); + out->cur += out->opts->margin_len; + } + for (; 0 < cnt; cnt--) { + *out->cur++ = ' '; + } } } -inline static void -fill_value(Out out, const char *value, size_t len) { +inline static void fill_value(Out out, const char *value, size_t len) { if (6 < len) { - memcpy(out->cur, value, len); - out->cur += len; + memcpy(out->cur, value, len); + out->cur += len; } else { - for (; 0 < len; len--, value++) { - *out->cur++ = *value; - } + for (; 0 < len; len--, value++) { + *out->cur++ = *value; + } } } -inline static void -fill_attr(Out out, char name, const char *value, size_t len) { +inline static void fill_attr(Out out, char name, const char *value, size_t len) { *out->cur++ = ' '; *out->cur++ = name; *out->cur++ = '='; *out->cur++ = '"'; if (6 < len) { - memcpy(out->cur, value, len); - out->cur += len; + memcpy(out->cur, value, len); + out->cur += len; } else { - for (; 0 < len; len--, value++) { - *out->cur++ = *value; - } + for (; 0 < len; len--, value++) { + *out->cur++ = *value; + } } *out->cur++ = '"'; } -inline static const char* -ulong2str(ulong num, char *end) { - char *b; +inline static const char *ulong2str(ulong num, char *end) { + char *b; *end-- = '\0'; for (b = end; 0 < num || b == end; num /= 10, b--) { - *b = (num % 10) + '0'; + *b = (num % 10) + '0'; } b++; return b; } -static int -check_circular(Out out, VALUE obj, Element e) { - slot_t *slot; - slot_t id; - int result; +static int check_circular(Out out, VALUE obj, Element e) { + slot_t *slot; + slot_t id; + int result; if (0 == (id = ox_cache8_get(out->circ_cache, obj, &slot))) { - out->circ_cnt++; - id = out->circ_cnt; - *slot = id; - e->id = id; - result = 0; + out->circ_cnt++; + id = out->circ_cnt; + *slot = id; + e->id = id; + result = 0; } else { - e->type = RefCode; e->clas.len = 0; e->clas.str = 0; - e->closed = 1; - e->id = id; - out->w_start(out, e); - result = 1; + e->type = RefCode; + e->clas.len = 0; + e->clas.str = 0; + e->closed = 1; + e->id = id; + out->w_start(out, e); + result = 1; } return result; } -static void -grow(Out out, size_t len) { - size_t size = out->end - out->buf; - long pos = out->cur - out->buf; +static void grow(Out out, size_t len) { + size_t size = out->end - out->buf; + long pos = out->cur - out->buf; size *= 2; if (size <= len * 2 + pos) { - size += len; + size += len; } 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) { - size_t size = e->indent + 4 + out->opts->margin_len; +static void dump_start(Out out, Element e) { + size_t size = e->indent + 4 + out->opts->margin_len; if (0 < e->attr.len) { /* a="attr" */ - size += e->attr.len + 5; + size += e->attr.len + 5; } if (0 < e->clas.len) { /* c="class" */ - size += e->clas.len + 5; + size += e->clas.len + 5; } if (0 < e->id) { /* i="id" */ - size += 24; /* over estimate, 19 digits */ + size += 24; /* over estimate, 19 digits */ } if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } if (out->buf + out->opts->margin_len < out->cur) { - fill_indent(out, e->indent); + fill_indent(out, e->indent); } *out->cur++ = '<'; *out->cur++ = e->type; if (0 < e->attr.len) { - fill_attr(out, 'a', e->attr.str, e->attr.len); + fill_attr(out, 'a', e->attr.str, e->attr.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 ((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) - 1; - const char *s = ulong2str(e->id, end); + char buf[32]; + char *end = buf + sizeof(buf) - 1; + const char *s = ulong2str(e->id, end); - fill_attr(out, 'i', s, end - s); + fill_attr(out, 'i', s, end - s); } if (e->closed) { - if (out->opts->no_empty) { - *out->cur++ = '>'; - *out->cur++ = '<'; - *out->cur++ = '/'; - *out->cur++ = e->type; - } else { - *out->cur++ = '/'; - } + if (out->opts->no_empty) { + *out->cur++ = '>'; + *out->cur++ = '<'; + *out->cur++ = '/'; + *out->cur++ = e->type; + } else { + *out->cur++ = '/'; + } } *out->cur++ = '>'; - *out->cur = '\0'; + *out->cur = '\0'; } -static void -dump_end(Out out, Element e) { - size_t size = e->indent + 5 + out->opts->margin_len; +static void dump_end(Out out, Element e) { + size_t size = e->indent + 5 + out->opts->margin_len; if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } fill_indent(out, e->indent); *out->cur++ = '<'; *out->cur++ = '/'; *out->cur++ = e->type; *out->cur++ = '>'; - *out->cur = '\0'; + *out->cur = '\0'; } -inline static void -dump_value(Out out, const char *value, size_t size) { +inline static void dump_value(Out out, const char *value, size_t size) { if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } if (6 < size) { - memcpy(out->cur, value, size); - out->cur += size; + memcpy(out->cur, value, size); + out->cur += size; } else { - for (; 0 < size; size--, value++) { - *out->cur++ = *value; - } + for (; 0 < size; size--, value++) { + *out->cur++ = *value; + } } *out->cur = '\0'; } -inline static void -dump_str_value(Out out, const char *value, size_t size, const char *table) { - size_t xsize = xml_str_len((const uchar*)value, size, table); +inline static void dump_str_value(Out out, const char *value, size_t size, const char *table) { + size_t xsize = xml_str_len((const uchar *)value, size, table); if (out->end - out->cur <= (long)xsize) { - grow(out, xsize); + grow(out, xsize); } for (; 0 < size; size--, value++) { - if ('1' == table[(uchar)*value]) { - *out->cur++ = *value; - } else { - switch (*value) { - case '"': - *out->cur++ = '&'; - *out->cur++ = 'q'; - *out->cur++ = 'u'; - *out->cur++ = 'o'; - *out->cur++ = 't'; - *out->cur++ = ';'; - break; - case '&': - *out->cur++ = '&'; - *out->cur++ = 'a'; - *out->cur++ = 'm'; - *out->cur++ = 'p'; - *out->cur++ = ';'; - break; - case '\'': - *out->cur++ = '&'; - *out->cur++ = 'a'; - *out->cur++ = 'p'; - *out->cur++ = 'o'; - *out->cur++ = 's'; - *out->cur++ = ';'; - break; - case '<': - *out->cur++ = '&'; - *out->cur++ = 'l'; - *out->cur++ = 't'; - *out->cur++ = ';'; - break; - case '>': - *out->cur++ = '&'; - *out->cur++ = 'g'; - *out->cur++ = 't'; - *out->cur++ = ';'; - break; - default: - // Must be one of the invalid characters. - if (StrictEffort == out->opts->effort) { - rb_raise(ox_syntax_error_class, "'\\#x%02x' is not a valid XML character.", *value); - } - if (Yes == out->opts->allow_invalid) { - *out->cur++ = '&'; - *out->cur++ = '#'; - *out->cur++ = 'x'; - *out->cur++ = '0'; - *out->cur++ = '0'; - dump_hex(*value, out); - *out->cur++ = ';'; - } else if ('\0' != *out->opts->inv_repl) { - // If the empty string then ignore. The first character of - // the replacement is the length. - memcpy(out->cur, out->opts->inv_repl + 1, (size_t)*out->opts->inv_repl); - out->cur += *out->opts->inv_repl; - } - break; - } - } + if ('1' == table[(uchar)*value]) { + *out->cur++ = *value; + } else { + switch (*value) { + case '"': + *out->cur++ = '&'; + *out->cur++ = 'q'; + *out->cur++ = 'u'; + *out->cur++ = 'o'; + *out->cur++ = 't'; + *out->cur++ = ';'; + break; + case '&': + *out->cur++ = '&'; + *out->cur++ = 'a'; + *out->cur++ = 'm'; + *out->cur++ = 'p'; + *out->cur++ = ';'; + break; + case '\'': + *out->cur++ = '&'; + *out->cur++ = 'a'; + *out->cur++ = 'p'; + *out->cur++ = 'o'; + *out->cur++ = 's'; + *out->cur++ = ';'; + break; + case '<': + *out->cur++ = '&'; + *out->cur++ = 'l'; + *out->cur++ = 't'; + *out->cur++ = ';'; + break; + case '>': + *out->cur++ = '&'; + *out->cur++ = 'g'; + *out->cur++ = 't'; + *out->cur++ = ';'; + break; + default: + // Must be one of the invalid characters. + if (StrictEffort == out->opts->effort) { + rb_raise(ox_syntax_error_class, "'\\#x%02x' is not a valid XML character.", *value); + } + if (Yes == out->opts->allow_invalid) { + *out->cur++ = '&'; + *out->cur++ = '#'; + *out->cur++ = 'x'; + *out->cur++ = '0'; + *out->cur++ = '0'; + dump_hex(*value, out); + *out->cur++ = ';'; + } else if ('\0' != *out->opts->inv_repl) { + // If the empty string then ignore. The first character of + // the replacement is the length. + memcpy(out->cur, out->opts->inv_repl + 1, (size_t)*out->opts->inv_repl); + out->cur += *out->opts->inv_repl; + } + break; + } + } } *out->cur = '\0'; } -inline static void -dump_num(Out out, VALUE obj) { - char buf[32]; - char *b = buf + sizeof(buf) - 1; - long num = NUM2LONG(obj); - int neg = 0; +inline static void dump_num(Out out, VALUE obj) { + char buf[32]; + char *b = buf + sizeof(buf) - 1; + long num = NUM2LONG(obj); + int neg = 0; if (0 > num) { - neg = 1; - num = -num; + neg = 1; + num = -num; } *b-- = '\0'; if (0 < num) { - for (; 0 < num; num /= 10, b--) { - *b = (num % 10) + '0'; - } - if (neg) { - *b = '-'; - } else { - b++; - } + for (; 0 < num; num /= 10, b--) { + *b = (num % 10) + '0'; + } + if (neg) { + *b = '-'; + } else { + b++; + } } else { - *b = '0'; + *b = '0'; } if (out->end - out->cur <= (long)(sizeof(buf) - (b - buf))) { - grow(out, sizeof(buf) - (b - buf)); + grow(out, sizeof(buf) - (b - buf)); } for (; '\0' != *b; b++) { - *out->cur++ = *b; + *out->cur++ = *b; } *out->cur = '\0'; } -static void -dump_time_thin(Out out, VALUE obj) { - char buf[64]; - char *b = buf + sizeof(buf) - 1; +static void dump_time_thin(Out out, VALUE obj) { + char buf[64]; + char *b = buf + sizeof(buf) - 1; #if HAVE_RB_TIME_TIMESPEC - struct timespec ts = rb_time_timespec(obj); - time_t sec = ts.tv_sec; - long nsec = ts.tv_nsec; + struct timespec ts = rb_time_timespec(obj); + time_t sec = ts.tv_sec; + long nsec = ts.tv_nsec; #else - time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0)); - long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0)); - //long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000; + time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0)); + long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0)); + // long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000; #endif - char *dot = b - 10; - long size; + char *dot = b - 10; + long size; *b-- = '\0'; for (; dot < b; b--, nsec /= 10) { - *b = '0' + (nsec % 10); + *b = '0' + (nsec % 10); } *b-- = '.'; for (; 0 < sec; b--, sec /= 10) { - *b = '0' + (sec % 10); + *b = '0' + (sec % 10); } b++; size = sizeof(buf) - (b - buf) - 1; if (out->end - out->cur <= size) { - grow(out, size); + grow(out, size); } 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; +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 = '0' + (jd % 10); } b++; if ('\0' == *b) { - b--; - *b = '0'; + b--; + *b = '0'; } size = sizeof(buf) - (b - buf) - 1; if (out->end - out->cur <= size) { - grow(out, size); + grow(out, size); } memcpy(out->cur, b, size); out->cur += size; } -static void -dump_time_xsd(Out out, VALUE obj) { - struct tm *tm; +static void dump_time_xsd(Out out, VALUE obj) { + struct tm *tm; #if HAVE_RB_TIME_TIMESPEC - struct timespec ts = rb_time_timespec(obj); - time_t sec = ts.tv_sec; - long nsec = ts.tv_nsec; + struct timespec ts = rb_time_timespec(obj); + time_t sec = ts.tv_sec; + long nsec = ts.tv_nsec; #else - time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0)); - long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0)); - //long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000; + time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0)); + long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0)); + // long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000; #endif - int tzhour, tzmin; - char tzsign = '+'; + int tzhour, tzmin; + char tzsign = '+'; if (out->end - out->cur <= 33) { - grow(out, 33); + grow(out, 33); } /* 2010-07-09T10:47:45.895826+09:00 */ tm = localtime(&sec); #if HAVE_ST_TM_GMTOFF if (0 > tm->tm_gmtoff) { - tzsign = '-'; - tzhour = (int)(tm->tm_gmtoff / -3600); - tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60); + tzsign = '-'; + tzhour = (int)(tm->tm_gmtoff / -3600); + tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60); } else { - tzhour = (int)(tm->tm_gmtoff / 3600); - tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60); + tzhour = (int)(tm->tm_gmtoff / 3600); + tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60); } #else tzhour = 0; - tzmin = 0; + tzmin = 0; #endif /* TBD replace with more efficient printer */ - out->cur += sprintf(out->cur, "%04d-%02d-%02dT%02d:%02d:%02d.%06ld%c%02d:%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, nsec / 1000, - tzsign, tzhour, tzmin); + out->cur += sprintf(out->cur, + "%04d-%02d-%02dT%02d:%02d:%02d.%06ld%c%02d:%02d", + tm->tm_year + 1900, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + nsec / 1000, + tzsign, + tzhour, + tzmin); } -static void -dump_first_obj(VALUE obj, Out out) { - char buf[128]; - Options copts = out->opts; - int cnt; +static void dump_first_obj(VALUE obj, Out out) { + char buf[128]; + Options copts = out->opts; + int cnt; if (Yes == copts->with_xml) { - if (0 < copts->margin_len) { - dump_value(out, copts->margin, copts->margin_len); - } - if ('\0' == *copts->encoding) { - dump_value(out, "<?xml version=\"1.0\"?>", 21); - } else { - cnt = snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"%s\"?>", copts->encoding); - dump_value(out, buf, cnt); - } + if (0 < copts->margin_len) { + dump_value(out, copts->margin, copts->margin_len); + } + if ('\0' == *copts->encoding) { + dump_value(out, "<?xml version=\"1.0\"?>", 21); + } else { + cnt = snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"%s\"?>", copts->encoding); + dump_value(out, buf, cnt); + } } if (Yes == copts->with_instruct) { - if (out->buf < out->cur) { - dump_value(out, "\n", 1); - } - if (0 < copts->margin_len) { - dump_value(out, copts->margin, copts->margin_len); - } - cnt = snprintf(buf, sizeof(buf), "<?ox version=\"1.0\" mode=\"object\"%s%s?>", - (Yes == copts->circular) ? " circular=\"yes\"" : ((No == copts->circular) ? " circular=\"no\"" : ""), - (Yes == copts->xsd_date) ? " xsd_date=\"yes\"" : ((No == copts->xsd_date) ? " xsd_date=\"no\"" : "")); - dump_value(out, buf, cnt); + if (out->buf < out->cur) { + dump_value(out, "\n", 1); + } + if (0 < copts->margin_len) { + dump_value(out, copts->margin, copts->margin_len); + } + cnt = snprintf( + buf, + sizeof(buf), + "<?ox version=\"1.0\" mode=\"object\"%s%s?>", + (Yes == copts->circular) ? " circular=\"yes\"" : ((No == copts->circular) ? " circular=\"no\"" : ""), + (Yes == copts->xsd_date) ? " xsd_date=\"yes\"" : ((No == copts->xsd_date) ? " xsd_date=\"no\"" : "")); + dump_value(out, buf, cnt); } if (Yes == copts->with_dtd) { - if (0 < copts->margin_len) { - dump_value(out, copts->margin, copts->margin_len); - } - cnt = snprintf(buf, sizeof(buf), "%s<!DOCTYPE %c SYSTEM \"ox.dtd\">", (out->buf < out->cur) ? "\n" : "", obj_class_code(obj)); - dump_value(out, buf, cnt); + if (0 < copts->margin_len) { + dump_value(out, copts->margin, copts->margin_len); + } + cnt = snprintf(buf, + sizeof(buf), + "%s<!DOCTYPE %c SYSTEM \"ox.dtd\">", + (out->buf < out->cur) ? "\n" : "", + obj_class_code(obj)); + dump_value(out, buf, cnt); } if (0 < copts->margin_len) { - dump_value(out, copts->margin, copts->margin_len); + dump_value(out, copts->margin, copts->margin_len); } dump_obj(0, obj, 0, out); } -static void -dump_obj(ID aid, VALUE obj, int depth, Out out) { - struct _element e; - VALUE prev_obj = out->obj; - char value_buf[64]; - int cnt; +static void dump_obj(ID aid, VALUE obj, int depth, Out out) { + struct _element e; + VALUE prev_obj = out->obj; + char value_buf[64]; + int cnt; if (MAX_DEPTH < depth) { - rb_raise(rb_eSysStackError, "maximum depth exceeded"); + rb_raise(rb_eSysStackError, "maximum depth exceeded"); } out->obj = obj; if (0 == aid) { - e.attr.str = 0; - e.attr.len = 0; + e.attr.str = 0; + e.attr.len = 0; } else { - e.attr.str = rb_id2name(aid); - // Ruby 2.3 started to return NULL for some IDs so check for - // NULL. Ignore if NULL aid. - if (NULL == e.attr.str) { - return; - } - e.attr.len = strlen(e.attr.str); + e.attr.str = rb_id2name(aid); + // Ruby 2.3 started to return NULL for some IDs so check for + // NULL. Ignore if NULL aid. + if (NULL == e.attr.str) { + return; + } + e.attr.len = strlen(e.attr.str); } e.closed = 0; if (0 == depth) { - e.indent = (0 <= out->indent) ? 0 : -1; + e.indent = (0 <= out->indent) ? 0 : -1; } else if (0 > out->indent) { - e.indent = -1; + e.indent = -1; } else if (0 == out->indent) { - e.indent = 0; + e.indent = 0; } else { - e.indent = depth * out->indent; + e.indent = depth * out->indent; } - e.id = 0; + e.id = 0; e.clas.len = 0; e.clas.str = 0; switch (rb_type(obj)) { case T_NIL: - e.type = NilClassCode; - e.closed = 1; - out->w_start(out, &e); - break; + e.type = NilClassCode; + e.closed = 1; + out->w_start(out, &e); + break; case T_ARRAY: - if (0 != out->circ_cache && check_circular(out, obj, &e)) { - break; - } - cnt = (int)RARRAY_LEN(obj); - e.type = ArrayCode; - e.closed = (0 >= cnt); - out->w_start(out, &e); - if (!e.closed) { - const VALUE *np = RARRAY_PTR(obj); - int i; - int d2 = depth + 1; + if (0 != out->circ_cache && check_circular(out, obj, &e)) { + break; + } + cnt = (int)RARRAY_LEN(obj); + e.type = ArrayCode; + e.closed = (0 >= cnt); + out->w_start(out, &e); + if (!e.closed) { + const VALUE *np = RARRAY_PTR(obj); + int i; + int d2 = depth + 1; - for (i = cnt; 0 < i; i--, np++) { - dump_obj(0, *np, d2, out); - } - out->w_end(out, &e); - } - break; + for (i = cnt; 0 < i; i--, np++) { + dump_obj(0, *np, d2, out); + } + out->w_end(out, &e); + } + break; case T_HASH: - if (0 != out->circ_cache && check_circular(out, obj, &e)) { - break; - } - cnt = (int)RHASH_SIZE(obj); - e.type = HashCode; - e.closed = (0 >= cnt); - out->w_start(out, &e); - if (0 < cnt) { - unsigned int od = out->depth; + if (0 != out->circ_cache && check_circular(out, obj, &e)) { + break; + } + cnt = (int)RHASH_SIZE(obj); + e.type = HashCode; + e.closed = (0 >= cnt); + out->w_start(out, &e); + if (0 < cnt) { + unsigned int od = out->depth; - out->depth = depth + 1; - rb_hash_foreach(obj, dump_hash, (VALUE)out); - out->depth = od; - out->w_end(out, &e); - } - break; + out->depth = depth + 1; + rb_hash_foreach(obj, dump_hash, (VALUE)out); + out->depth = od; + out->w_end(out, &e); + } + break; case T_TRUE: - e.type = TrueClassCode; - e.closed = 1; - out->w_start(out, &e); - break; + e.type = TrueClassCode; + e.closed = 1; + out->w_start(out, &e); + break; case T_FALSE: - e.type = FalseClassCode; - e.closed = 1; - out->w_start(out, &e); - break; + e.type = FalseClassCode; + e.closed = 1; + out->w_start(out, &e); + break; case T_FIXNUM: - e.type = FixnumCode; - out->w_start(out, &e); - dump_num(out, obj); - e.indent = -1; - out->w_end(out, &e); - break; + e.type = FixnumCode; + out->w_start(out, &e); + dump_num(out, obj); + e.indent = -1; + out->w_end(out, &e); + break; case T_FLOAT: - e.type = FloatCode; - cnt = snprintf(value_buf, sizeof(value_buf), "%0.16g", rb_num2dbl(obj)); - out->w_start(out, &e); - dump_value(out, value_buf, cnt); - e.indent = -1; - out->w_end(out, &e); - break; - case T_STRING: - { - const char *str; + e.type = FloatCode; + cnt = snprintf(value_buf, sizeof(value_buf), "%0.16g", rb_num2dbl(obj)); + out->w_start(out, &e); + dump_value(out, value_buf, cnt); + e.indent = -1; + out->w_end(out, &e); + break; + case T_STRING: { + const char *str; - if (0 != out->circ_cache && check_circular(out, obj, &e)) { - break; - } - str = StringValuePtr(obj); - cnt = (int)RSTRING_LEN(obj); + if (0 != out->circ_cache && check_circular(out, obj, &e)) { + break; + } + str = StringValuePtr(obj); + cnt = (int)RSTRING_LEN(obj); #if USE_B64 - if (is_xml_friendly((uchar*)str, cnt)) { - e.type = StringCode; - out->w_start(out, &e); - dump_str_value(out, str, cnt, '<'); - e.indent = -1; - out->w_end(out, &e); - } else { - ulong size = b64_size(cnt); - char *b64 = ALLOCA_N(char, size + 1); + if (is_xml_friendly((uchar *)str, cnt)) { + e.type = StringCode; + out->w_start(out, &e); + dump_str_value(out, str, cnt, '<'); + e.indent = -1; + out->w_end(out, &e); + } else { + ulong size = b64_size(cnt); + char *b64 = ALLOCA_N(char, size + 1); - e.type = String64Code; - to_base64((uchar*)str, cnt, b64); - out->w_start(out, &e); - dump_value(out, b64, size); - e.indent = -1; - out->w_end(out, &e); - } + e.type = String64Code; + to_base64((uchar *)str, cnt, b64); + out->w_start(out, &e); + dump_value(out, b64, size); + e.indent = -1; + out->w_end(out, &e); + } #else - e.type = StringCode; - out->w_start(out, &e); - dump_str_value(out, str, cnt, xml_element_chars); - e.indent = -1; - out->w_end(out, &e); + e.type = StringCode; + out->w_start(out, &e); + dump_str_value(out, str, cnt, xml_element_chars); + e.indent = -1; + out->w_end(out, &e); #endif - break; + break; } - case T_SYMBOL: - { - const char *sym = rb_id2name(SYM2ID(obj)); + case T_SYMBOL: { + const char *sym = rb_id2name(SYM2ID(obj)); - cnt = (int)strlen(sym); + cnt = (int)strlen(sym); #if USE_B64 - if (is_xml_friendly((uchar*)sym, cnt)) { - e.type = SymbolCode; - out->w_start(out, &e); - dump_str_value(out, sym, cnt, '<'); - e.indent = -1; - out->w_end(out, &e); - } else { - ulong size = b64_size(cnt); - char *b64 = ALLOCA_N(char, size + 1); + if (is_xml_friendly((uchar *)sym, cnt)) { + e.type = SymbolCode; + out->w_start(out, &e); + dump_str_value(out, sym, cnt, '<'); + e.indent = -1; + out->w_end(out, &e); + } else { + ulong size = b64_size(cnt); + char *b64 = ALLOCA_N(char, size + 1); - e.type = Symbol64Code; - to_base64((uchar*)sym, cnt, b64); - out->w_start(out, &e); - dump_value(out, b64, size); - e.indent = -1; - out->w_end(out, &e); - } + e.type = Symbol64Code; + to_base64((uchar *)sym, cnt, b64); + out->w_start(out, &e); + dump_value(out, b64, size); + e.indent = -1; + out->w_end(out, &e); + } #else - e.type = SymbolCode; - out->w_start(out, &e); - dump_str_value(out, sym, cnt, xml_element_chars); - e.indent = -1; - out->w_end(out, &e); + e.type = SymbolCode; + out->w_start(out, &e); + dump_str_value(out, sym, cnt, xml_element_chars); + e.indent = -1; + out->w_end(out, &e); #endif - break; + break; } - case T_DATA: - { - VALUE clas; + case T_DATA: { + VALUE clas; - clas = rb_obj_class(obj); - if (rb_cTime == clas) { - e.type = TimeCode; - out->w_start(out, &e); - out->w_time(out, obj); - e.indent = -1; - out->w_end(out, &e); - } else { - const char *classname = rb_class2name(clas); + clas = rb_obj_class(obj); + if (rb_cTime == clas) { + e.type = TimeCode; + out->w_start(out, &e); + out->w_time(out, obj); + e.indent = -1; + out->w_end(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 (0 == strcmp("BigDecimal", classname)) { - volatile VALUE rs = rb_funcall(obj, ox_to_s_id, 0); + 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 (0 == strcmp("BigDecimal", classname)) { + volatile VALUE rs = rb_funcall(obj, ox_to_s_id, 0); - e.type = BigDecimalCode; - out->w_start(out, &e); - dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs)); - 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; + e.type = BigDecimalCode; + out->w_start(out, &e); + dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs)); + 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: - { + case T_STRUCT: { #ifdef RSTRUCT_GET - VALUE clas; + VALUE clas; - if (0 != out->circ_cache && check_circular(out, obj, &e)) { - break; - } - clas = rb_obj_class(obj); - if (rb_cRange == clas) { - VALUE beg = RSTRUCT_GET(obj, 0); - VALUE end = RSTRUCT_GET(obj, 1); - VALUE excl = RSTRUCT_GET(obj, 2); - int d2 = depth + 1; + if (0 != out->circ_cache && check_circular(out, obj, &e)) { + break; + } + clas = rb_obj_class(obj); + if (rb_cRange == clas) { + VALUE beg = RSTRUCT_GET(obj, 0); + VALUE end = RSTRUCT_GET(obj, 1); + VALUE excl = RSTRUCT_GET(obj, 2); + int d2 = depth + 1; - e.type = RangeCode; e.clas.len = 5; e.clas.str = "Range"; - out->w_start(out, &e); - dump_obj(ox_beg_id, beg, d2, out); - dump_obj(ox_end_id, end, d2, out); - dump_obj(ox_excl_id, excl, d2, out); - out->w_end(out, &e); - } else { - char num_buf[16]; - int d2 = depth + 1; + e.type = RangeCode; + e.clas.len = 5; + e.clas.str = "Range"; + out->w_start(out, &e); + dump_obj(ox_beg_id, beg, d2, out); + dump_obj(ox_end_id, end, d2, out); + dump_obj(ox_excl_id, excl, d2, out); + out->w_end(out, &e); + } else { + char num_buf[16]; + int d2 = depth + 1; #ifdef RUBY_INTEGER_UNIFICATION - long i; - long cnt = NUM2LONG(rb_struct_size(obj)); -#else // UNIFY_FIXNUM_AND_INTEGER - int i; - int cnt = (int)RSTRUCT_LEN(obj); -#endif // UNIFY_FIXNUM_AND_INTEGER - e.type = StructCode; - e.clas.str = rb_class2name(clas); - e.clas.len = strlen(e.clas.str); - out->w_start(out, &e); + long i; + long cnt = NUM2LONG(rb_struct_size(obj)); +#else // UNIFY_FIXNUM_AND_INTEGER + int i; + int cnt = (int)RSTRUCT_LEN(obj); +#endif // UNIFY_FIXNUM_AND_INTEGER + e.type = StructCode; + e.clas.str = rb_class2name(clas); + e.clas.len = strlen(e.clas.str); + out->w_start(out, &e); - for (i = 0; i < cnt; i++) { - VALUE v = RSTRUCT_GET(obj, (int)(i)); - dump_obj(rb_intern(ulong2str(i, num_buf + sizeof(num_buf) - 1)), v, d2, out); - } - out->w_end(out, &e); - } + for (i = 0; i < cnt; i++) { + VALUE v = RSTRUCT_GET(obj, (int)(i)); + dump_obj(rb_intern(ulong2str(i, num_buf + sizeof(num_buf) - 1)), v, d2, out); + } + out->w_end(out, &e); + } #else - e.type = NilClassCode; - e.closed = 1; - out->w_start(out, &e); + e.type = NilClassCode; + e.closed = 1; + out->w_start(out, &e); #endif - break; + break; } - case T_OBJECT: - { - VALUE clas; + case T_OBJECT: { + VALUE clas; - if (0 != out->circ_cache && check_circular(out, obj, &e)) { - break; - } - clas = rb_obj_class(obj); - e.clas.str = rb_class2name(clas); - e.clas.len = strlen(e.clas.str); - if (ox_document_clas == clas) { - e.type = RawCode; - out->w_start(out, &e); - dump_gen_doc(obj, depth + 1, out); - out->w_end(out, &e); - } else if (ox_element_clas == clas) { - e.type = RawCode; - out->w_start(out, &e); - dump_gen_element(obj, depth + 1, out); - out->w_end(out, &e); - } else { /* Object */ + if (0 != out->circ_cache && check_circular(out, obj, &e)) { + break; + } + clas = rb_obj_class(obj); + e.clas.str = rb_class2name(clas); + e.clas.len = strlen(e.clas.str); + if (ox_document_clas == clas) { + e.type = RawCode; + out->w_start(out, &e); + dump_gen_doc(obj, depth + 1, out); + out->w_end(out, &e); + } else if (ox_element_clas == clas) { + e.type = RawCode; + out->w_start(out, &e); + dump_gen_element(obj, depth + 1, out); + out->w_end(out, &e); + } else { /* Object */ #if HAVE_RB_IVAR_FOREACH - 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; + 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; - out->depth = depth + 1; - rb_ivar_foreach(obj, dump_var, (VALUE)out); - out->depth = od; - out->w_end(out, &e); - } + out->depth = depth + 1; + rb_ivar_foreach(obj, dump_var, (VALUE)out); + out->depth = od; + out->w_end(out, &e); + } #else - volatile VALUE vars = rb_obj_instance_variables(obj); - //volatile VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0); + volatile VALUE vars = rb_obj_instance_variables(obj); + // volatile VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0); - 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) { - const VALUE *np = RARRAY_PTR(vars); - ID vid; - unsigned int od = out->depth; - int i; + 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) { + const VALUE *np = RARRAY_PTR(vars); + ID vid; + unsigned int od = out->depth; + int i; - out->depth = depth + 1; - for (i = cnt; 0 < i; i--, np++) { - vid = rb_to_id(*np); - dump_var(vid, rb_ivar_get(obj, vid), out); - } - out->depth = od; - out->w_end(out, &e); - } + out->depth = depth + 1; + for (i = cnt; 0 < i; i--, np++) { + vid = rb_to_id(*np); + dump_var(vid, rb_ivar_get(obj, vid), out); + } + out->depth = od; + out->w_end(out, &e); + } #endif - } - break; + } + break; } - case T_REGEXP: - { - volatile VALUE rs = rb_funcall2(obj, ox_inspect_id, 0, 0); - const char *s = StringValuePtr(rs); + case T_REGEXP: { + volatile VALUE rs = rb_funcall2(obj, ox_inspect_id, 0, 0); + const char *s = StringValuePtr(rs); - cnt = (int)RSTRING_LEN(rs); - e.type = RegexpCode; - out->w_start(out, &e); + cnt = (int)RSTRING_LEN(rs); + e.type = RegexpCode; + out->w_start(out, &e); #if USE_B64 - if (is_xml_friendly((uchar*)s, cnt)) { - /*dump_value(out, "/", 1); */ - dump_str_value(out, s, cnt, '<'); - } else { - ulong size = b64_size(cnt); - char *b64 = ALLOCA_N(char, size + 1); + if (is_xml_friendly((uchar *)s, cnt)) { + /*dump_value(out, "/", 1); */ + dump_str_value(out, s, cnt, '<'); + } else { + ulong size = b64_size(cnt); + char *b64 = ALLOCA_N(char, size + 1); - to_base64((uchar*)s, cnt, b64); - dump_value(out, b64, size); - } + to_base64((uchar *)s, cnt, b64); + dump_value(out, b64, size); + } #else - dump_str_value(out, s, cnt, xml_element_chars); + dump_str_value(out, s, cnt, xml_element_chars); #endif - e.indent = -1; - out->w_end(out, &e); - break; + e.indent = -1; + out->w_end(out, &e); + break; } - case T_BIGNUM: - { - volatile VALUE rs = rb_big2str(obj, 10); + case T_BIGNUM: { + volatile VALUE rs = rb_big2str(obj, 10); - e.type = BignumCode; - out->w_start(out, &e); - dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs)); - e.indent = -1; - out->w_end(out, &e); - break; + e.type = BignumCode; + out->w_start(out, &e); + dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs)); + e.indent = -1; + out->w_end(out, &e); + break; } #ifdef T_COMPLEX - case T_COMPLEX: - e.type = ComplexCode; - out->w_start(out, &e); + case T_COMPLEX: e.type = ComplexCode; out->w_start(out, &e); #ifdef RCOMPLEX - dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out); - dump_obj(0, RCOMPLEX(obj)->imag, depth + 1, out); + dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out); + dump_obj(0, RCOMPLEX(obj)->imag, depth + 1, out); #else - dump_obj(0, rb_funcall2(obj, rb_intern("real"), 0, 0), depth + 1, out); - dump_obj(0, rb_funcall2(obj, rb_intern("imag"), 0, 0), depth + 1, out); + dump_obj(0, rb_funcall2(obj, rb_intern("real"), 0, 0), depth + 1, out); + dump_obj(0, rb_funcall2(obj, rb_intern("imag"), 0, 0), depth + 1, out); #endif - out->w_end(out, &e); - break; + out->w_end(out, &e); + break; #endif #ifdef T_RATIONAL - case T_RATIONAL: - e.type = RationalCode; - out->w_start(out, &e); + case T_RATIONAL: e.type = RationalCode; out->w_start(out, &e); #ifdef RRATIONAL - dump_obj(0, RRATIONAL(obj)->num, depth + 1, out); - dump_obj(0, RRATIONAL(obj)->den, depth + 1, out); + dump_obj(0, RRATIONAL(obj)->num, depth + 1, out); + dump_obj(0, RRATIONAL(obj)->den, depth + 1, out); #else - dump_obj(0, rb_funcall2(obj, rb_intern("numerator"), 0, 0), depth + 1, out); - dump_obj(0, rb_funcall2(obj, rb_intern("denominator"), 0, 0), depth + 1, out); + dump_obj(0, rb_funcall2(obj, rb_intern("numerator"), 0, 0), depth + 1, out); + dump_obj(0, rb_funcall2(obj, rb_intern("denominator"), 0, 0), depth + 1, out); #endif - out->w_end(out, &e); - break; + out->w_end(out, &e); + break; #endif - case T_CLASS: - { - e.type = ClassCode; - e.clas.str = rb_class2name(obj); - e.clas.len = strlen(e.clas.str); - e.closed = 1; - out->w_start(out, &e); - break; + case T_CLASS: { + e.type = ClassCode; + e.clas.str = rb_class2name(obj); + e.clas.len = strlen(e.clas.str); + e.closed = 1; + out->w_start(out, &e); + break; } default: - if (StrictEffort == out->opts->effort) { - rb_raise(rb_eNotImpError, "Failed to dump %s Object (%02x)\n", - rb_obj_classname(obj), rb_type(obj)); - } else { - e.type = NilClassCode; - e.closed = 1; - out->w_start(out, &e); - } - break; + if (StrictEffort == out->opts->effort) { + rb_raise(rb_eNotImpError, "Failed to dump %s Object (%02x)\n", rb_obj_classname(obj), rb_type(obj)); + } else { + e.type = NilClassCode; + e.closed = 1; + out->w_start(out, &e); + } + break; } out->obj = prev_obj; } -static int -dump_var(ID key, VALUE value, VALUE ov) { - Out out = (Out)ov; +static int dump_var(ID key, VALUE value, VALUE ov) { + Out out = (Out)ov; if (T_DATA == rb_type(value) && key == ox_mesg_id) { - /* There is a secret recipe that keeps Exception mesg attributes as a - * T_DATA until it is needed. The safe way around this hack is to call - * the message() method and use the returned string as the - * message. Not pretty but it solves the most common use of this - * hack. If there are others they will have to be handled one at a - * time. - */ - value = rb_funcall(out->obj, ox_message_id, 0); + /* There is a secret recipe that keeps Exception mesg attributes as a + * T_DATA until it is needed. The safe way around this hack is to call + * the message() method and use the returned string as the + * message. Not pretty but it solves the most common use of this + * hack. If there are others they will have to be handled one at a + * time. + */ + value = rb_funcall(out->obj, ox_message_id, 0); } dump_obj(key, value, out->depth, out); return ST_CONTINUE; } -static int -dump_hash(VALUE key, VALUE value, VALUE ov) { - Out out = (Out)ov; +static int dump_hash(VALUE key, VALUE value, VALUE ov) { + Out out = (Out)ov; dump_obj(0, key, out->depth, out); dump_obj(0, value, out->depth, out); return ST_CONTINUE; } -static void -dump_gen_doc(VALUE obj, int depth, Out out) { - volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); - volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id); +static void dump_gen_doc(VALUE obj, int depth, Out out) { + volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); + volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id); if ('\0' == *out->opts->encoding && Qnil != attrs) { - volatile VALUE renc = rb_hash_lookup(attrs, ox_encoding_sym); + volatile VALUE renc = rb_hash_lookup(attrs, ox_encoding_sym); - if (Qnil != renc) { - const char *enc = StringValuePtr(renc); + if (Qnil != renc) { + const char *enc = StringValuePtr(renc); - strncpy(out->opts->encoding, enc, sizeof(out->opts->encoding) - 1); - } + strncpy(out->opts->encoding, enc, sizeof(out->opts->encoding) - 1); + } } if (Yes == out->opts->with_xml) { - if (0 < out->opts->margin_len) { - dump_value(out, out->opts->margin, out->opts->margin_len); - } - dump_value(out, "<?xml", 5); - if (Qnil != attrs) { - rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); - } - dump_value(out, "?>", 2); + if (0 < out->opts->margin_len) { + dump_value(out, out->opts->margin, out->opts->margin_len); + } + dump_value(out, "<?xml", 5); + if (Qnil != attrs) { + rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); + } + dump_value(out, "?>", 2); } if (Yes == out->opts->with_instruct) { - if (out->buf < out->cur) { - dump_value(out, "\n", 1); - } - if (0 < out->opts->margin_len) { - dump_value(out, out->opts->margin, out->opts->margin_len); - } - dump_value(out, "<?ox version=\"1.0\" mode=\"generic\"?>", 35); + if (out->buf < out->cur) { + dump_value(out, "\n", 1); + } + if (0 < out->opts->margin_len) { + dump_value(out, out->opts->margin, out->opts->margin_len); + } + dump_value(out, "<?ox version=\"1.0\" mode=\"generic\"?>", 35); } if (Qnil != nodes) { - dump_gen_nodes(nodes, depth, out); + dump_gen_nodes(nodes, depth, out); } } -static void -dump_gen_element(VALUE obj, int depth, Out out) { - volatile VALUE rname = rb_attr_get(obj, ox_at_value_id); - volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); - volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id); - const char *name = StringValuePtr(rname); - long nlen = RSTRING_LEN(rname); - size_t size; - int indent; +static void dump_gen_element(VALUE obj, int depth, Out out) { + volatile VALUE rname = rb_attr_get(obj, ox_at_value_id); + volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); + volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id); + const char *name = StringValuePtr(rname); + long nlen = RSTRING_LEN(rname); + size_t size; + int indent; if (0 > out->indent) { - indent = -1; + indent = -1; } else if (0 == out->indent) { - indent = 0; + indent = 0; } else { - indent = depth * out->indent; + indent = depth * out->indent; } size = indent + 4 + nlen + out->opts->margin_len; if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } if (0 == depth && 0 < out->opts->margin_len && 0 < out->indent) { - memcpy(out->cur, out->opts->margin, out->opts->margin_len); - out->cur += out->opts->margin_len; + memcpy(out->cur, out->opts->margin, out->opts->margin_len); + out->cur += out->opts->margin_len; } fill_indent(out, indent); *out->cur++ = '<'; fill_value(out, name, nlen); if (Qnil != attrs) { - rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); + rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); } if (Qnil != nodes && 0 < RARRAY_LEN(nodes)) { - int do_indent; + int do_indent; - *out->cur++ = '>'; - do_indent = dump_gen_nodes(nodes, depth, out); - if (out->end - out->cur <= (long)size) { - grow(out, size); - } - if (do_indent) { - fill_indent(out, indent); - } - *out->cur++ = '<'; - *out->cur++ = '/'; - fill_value(out, name, nlen); + *out->cur++ = '>'; + do_indent = dump_gen_nodes(nodes, depth, out); + if (out->end - out->cur <= (long)size) { + grow(out, size); + } + if (do_indent) { + fill_indent(out, indent); + } + *out->cur++ = '<'; + *out->cur++ = '/'; + fill_value(out, name, nlen); } else if (out->opts->no_empty) { - *out->cur++ = '>'; - *out->cur++ = '<'; - *out->cur++ = '/'; - fill_value(out, name, nlen); + *out->cur++ = '>'; + *out->cur++ = '<'; + *out->cur++ = '/'; + fill_value(out, name, nlen); } else { - *out->cur++ = '/'; + *out->cur++ = '/'; } *out->cur++ = '>'; - *out->cur = '\0'; + *out->cur = '\0'; } -static void -dump_gen_instruct(VALUE obj, int depth, Out out) { - volatile VALUE rname = rb_attr_get(obj, ox_at_value_id); - volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); - volatile VALUE rcontent = rb_attr_get(obj, ox_at_content_id); - const char *name = StringValuePtr(rname); - const char *content = 0; - long nlen = RSTRING_LEN(rname); - long clen = 0; - size_t size; +static void dump_gen_instruct(VALUE obj, int depth, Out out) { + volatile VALUE rname = rb_attr_get(obj, ox_at_value_id); + volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id); + volatile VALUE rcontent = rb_attr_get(obj, ox_at_content_id); + const char *name = StringValuePtr(rname); + const char *content = 0; + long nlen = RSTRING_LEN(rname); + long clen = 0; + size_t size; if (T_STRING == rb_type(rcontent)) { - content = StringValuePtr(rcontent); - clen = RSTRING_LEN(rcontent); - size = 4 + nlen + clen; + content = StringValuePtr(rcontent); + clen = RSTRING_LEN(rcontent); + size = 4 + nlen + clen; } else { - size = 4 + nlen; + size = 4 + nlen; } if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } *out->cur++ = '<'; *out->cur++ = '?'; fill_value(out, name, nlen); if (0 != content) { - fill_value(out, content, clen); + fill_value(out, content, clen); } else if (Qnil != attrs) { - rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); + rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out); } *out->cur++ = '?'; *out->cur++ = '>'; - *out->cur = '\0'; + *out->cur = '\0'; } -static int -dump_gen_nodes(VALUE obj, int depth, Out out) { - long cnt = RARRAY_LEN(obj); - int indent_needed = 1; +static int dump_gen_nodes(VALUE obj, int depth, Out out) { + long cnt = RARRAY_LEN(obj); + int indent_needed = 1; if (0 < cnt) { - const VALUE *np = RARRAY_PTR(obj); - VALUE clas; - int d2 = depth + 1; + const VALUE *np = RARRAY_PTR(obj); + VALUE clas; + int d2 = depth + 1; - if (MAX_DEPTH < depth) { - rb_raise(rb_eSysStackError, "maximum depth exceeded"); - } - for (; 0 < cnt; cnt--, np++) { - clas = rb_obj_class(*np); - if (ox_element_clas == clas) { - dump_gen_element(*np, d2, out); - } else if (ox_instruct_clas == clas) { - dump_gen_instruct(*np, d2, out); - indent_needed = (1 == cnt) ? 0 : 1; - } else if (rb_cString == clas) { - dump_str_value(out, StringValuePtr(*(VALUE*)np), RSTRING_LEN(*np), xml_element_chars); - indent_needed = (1 == cnt) ? 0 : 1; - } else if (ox_comment_clas == clas) { - dump_gen_val_node(*np, d2, "<!-- ", 5, " -->", 4, out); - } else if (ox_raw_clas == clas) { - dump_gen_val_node(*np, d2, "", 0, "", 0, out); - } else if (ox_cdata_clas == clas) { - dump_gen_val_node(*np, d2, "<![CDATA[", 9, "]]>", 3, out); - } else if (ox_doctype_clas == clas) { - dump_gen_val_node(*np, d2, "<!DOCTYPE ", 10, ">", 1, out); - } else { - rb_raise(rb_eTypeError, "Unexpected class, %s, while dumping generic XML\n", rb_class2name(clas)); - } - } + if (MAX_DEPTH < depth) { + rb_raise(rb_eSysStackError, "maximum depth exceeded"); + } + for (; 0 < cnt; cnt--, np++) { + clas = rb_obj_class(*np); + if (ox_element_clas == clas) { + dump_gen_element(*np, d2, out); + } else if (ox_instruct_clas == clas) { + dump_gen_instruct(*np, d2, out); + indent_needed = (1 == cnt) ? 0 : 1; + } else if (rb_cString == clas) { + dump_str_value(out, StringValuePtr(*(VALUE *)np), RSTRING_LEN(*np), xml_element_chars); + indent_needed = (1 == cnt) ? 0 : 1; + } else if (ox_comment_clas == clas) { + dump_gen_val_node(*np, d2, "<!-- ", 5, " -->", 4, out); + } else if (ox_raw_clas == clas) { + dump_gen_val_node(*np, d2, "", 0, "", 0, out); + } else if (ox_cdata_clas == clas) { + dump_gen_val_node(*np, d2, "<![CDATA[", 9, "]]>", 3, out); + } else if (ox_doctype_clas == clas) { + dump_gen_val_node(*np, d2, "<!DOCTYPE ", 10, ">", 1, out); + } else { + rb_raise(rb_eTypeError, "Unexpected class, %s, while dumping generic XML\n", rb_class2name(clas)); + } + } } return indent_needed; } -static int -dump_gen_attr(VALUE key, VALUE value, VALUE ov) { - Out out = (Out)ov; +static int dump_gen_attr(VALUE key, VALUE value, VALUE ov) { + Out out = (Out)ov; - const char *ks; - size_t klen; - size_t size; + const char *ks; + size_t klen; + size_t size; switch (rb_type(key)) { - case T_SYMBOL: - ks = rb_id2name(SYM2ID(key)); - break; - case T_STRING: - ks = StringValuePtr(key); - break; + case T_SYMBOL: ks = rb_id2name(SYM2ID(key)); break; + case T_STRING: ks = StringValuePtr(key); break; default: - key = rb_String(key); - ks = StringValuePtr(key); - break; + key = rb_String(key); + ks = StringValuePtr(key); + break; } - klen = strlen(ks); + klen = strlen(ks); value = rb_String(value); - size = 4 + klen + RSTRING_LEN(value); + size = 4 + klen + RSTRING_LEN(value); if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } *out->cur++ = ' '; fill_value(out, ks, klen); *out->cur++ = '='; *out->cur++ = '"'; @@ -1230,98 +1206,93 @@ return ST_CONTINUE; } static void -dump_gen_val_node(VALUE obj, int depth, - const char *pre, size_t plen, - const char *suf, size_t slen, Out out) { - volatile VALUE v = rb_attr_get(obj, ox_at_value_id); - const char *val; - size_t vlen; - size_t size; - int indent; +dump_gen_val_node(VALUE obj, int depth, const char *pre, size_t plen, const char *suf, size_t slen, Out out) { + volatile VALUE v = rb_attr_get(obj, ox_at_value_id); + const char *val; + size_t vlen; + size_t size; + int indent; if (T_STRING != rb_type(v)) { - return; + return; } - val = StringValuePtr(v); + val = StringValuePtr(v); vlen = RSTRING_LEN(v); if (0 > out->indent) { - indent = -1; + indent = -1; } else if (0 == out->indent) { - indent = 0; + indent = 0; } else { - indent = depth * out->indent; + indent = depth * out->indent; } size = indent + plen + slen + vlen + out->opts->margin_len; if (out->end - out->cur <= (long)size) { - grow(out, size); + grow(out, size); } fill_indent(out, indent); fill_value(out, pre, plen); fill_value(out, val, vlen); fill_value(out, suf, slen); *out->cur = '\0'; } -static void -dump_obj_to_xml(VALUE obj, Options copts, Out out) { - VALUE clas = rb_obj_class(obj); +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 = ALLOC_N(char, 65336); - out->end = out->buf + 65325; /* 10 less than end plus extra for possible errors */ - out->cur = out->buf; + out->w_time = (Yes == copts->xsd_date) ? dump_time_xsd : dump_time_thin; + 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; - *out->cur = '\0'; + out->circ_cnt = 0; + out->opts = copts; + out->obj = obj; + *out->cur = '\0'; if (Yes == copts->circular) { - ox_cache8_new(&out->circ_cache); + ox_cache8_new(&out->circ_cache); } out->indent = copts->indent; if (ox_document_clas == clas) { - dump_gen_doc(obj, -1, out); + dump_gen_doc(obj, -1, out); } else if (ox_element_clas == clas) { - dump_gen_element(obj, 0, out); + dump_gen_element(obj, 0, out); } else { - out->w_start = dump_start; - out->w_end = dump_end; - dump_first_obj(obj, out); + out->w_start = dump_start; + out->w_end = dump_end; + dump_first_obj(obj, out); } if (0 <= out->indent) { - dump_value(out, "\n", 1); + dump_value(out, "\n", 1); } if (Yes == copts->circular) { - ox_cache8_delete(out->circ_cache); + ox_cache8_delete(out->circ_cache); } } -char* -ox_write_obj_to_str(VALUE obj, Options copts) { +char *ox_write_obj_to_str(VALUE obj, Options copts) { struct _out out; dump_obj_to_xml(obj, copts, &out); return out.buf; } -void -ox_write_obj_to_file(VALUE obj, const char *path, Options copts) { +void ox_write_obj_to_file(VALUE obj, const char *path, Options copts) { struct _out out; - size_t size; - FILE *f; + size_t size; + FILE *f; dump_obj_to_xml(obj, copts, &out); size = out.cur - out.buf; if (0 == (f = fopen(path, "w"))) { - rb_raise(rb_eIOError, "%s\n", strerror(errno)); + rb_raise(rb_eIOError, "%s\n", strerror(errno)); } if (size != fwrite(out.buf, 1, size, f)) { - int err = ferror(f); - rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err)); + int err = ferror(f); + rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err)); } xfree(out.buf); fclose(f); }