Skip to content

Commit

Permalink
fixed on bug with leaf access
Browse files Browse the repository at this point in the history
  • Loading branch information
ohler55 committed Apr 14, 2015
1 parent af09175 commit 10a4af8
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 109 deletions.
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -26,6 +26,12 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme

[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)

## Future Release 2.12.2

- Fixed Oj::Doc bug that causes a crash on local name lookups.

- TBD Fixed Oj::Doc unicode parsing.

## Current Release 2.12.1

- Changed the unix_zone encoded format to be the utc epoch.
Expand Down
16 changes: 15 additions & 1 deletion ext/oj/buf.h
Expand Up @@ -49,7 +49,7 @@ buf_init(Buf buf) {

inline static void
buf_cleanup(Buf buf) {
if (buf->base != buf->head) {
if (buf->base != buf->head || 0 != buf->head) {
xfree(buf->head);
}
}
Expand All @@ -59,6 +59,20 @@ buf_len(Buf buf) {
return buf->tail - buf->head;
}

// allocates is necessary, return must be freed.
inline static char*
buf_take_str(Buf buf) {
char *s = buf->head;

if (buf->base != buf->head) {
s = buf->head;
buf->head = 0;
} else {
s = strdup(buf->head);
}
return s;
}

inline static void
buf_append_string(Buf buf, const char *s, size_t slen) {
if (buf->end <= buf->tail + slen) {
Expand Down
4 changes: 2 additions & 2 deletions ext/oj/dump.c
Expand Up @@ -2228,7 +2228,7 @@ dump_leaf_hash(Leaf leaf, int depth, Out out) {

static void
dump_leaf(Leaf leaf, int depth, Out out) {
switch (leaf->type) {
switch (leaf->rtype) {
case T_NIL:
dump_nil(out);
break;
Expand All @@ -2254,7 +2254,7 @@ dump_leaf(Leaf leaf, int depth, Out out) {
dump_leaf_hash(leaf, depth, out);
break;
default:
rb_raise(rb_eTypeError, "Unexpected type %02x.\n", leaf->type);
rb_raise(rb_eTypeError, "Unexpected type %02x.\n", leaf->rtype);
break;
}
}
Expand Down
106 changes: 18 additions & 88 deletions ext/oj/fast.c
Expand Up @@ -170,7 +170,7 @@ ulong_fill(char *s, size_t num) {
inline static void
leaf_init(Leaf leaf, int type) {
leaf->next = 0;
leaf->type = type;
leaf->rtype = type;
leaf->parent_type = T_NONE;
switch (type) {
case T_ARRAY:
Expand Down Expand Up @@ -206,6 +206,8 @@ leaf_new(Doc doc, int type) {
if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
Batch b = ALLOC(struct _Batch);

// Initializes all leaves with a NO_VAL value_type
memset(b, 0, sizeof(struct _Batch));
b->next = doc->batches;
doc->batches = b;
b->next_avail = 0;
Expand All @@ -232,7 +234,7 @@ leaf_append_element(Leaf parent, Leaf element) {
static VALUE
leaf_value(Doc doc, Leaf leaf) {
if (RUBY_VAL != leaf->value_type) {
switch (leaf->type) {
switch (leaf->rtype) {
case T_NIL:
leaf->value = Qnil;
break;
Expand Down Expand Up @@ -260,7 +262,7 @@ leaf_value(Doc doc, Leaf leaf) {
return leaf_hash_value(doc, leaf);
break;
default:
rb_raise(rb_const_get_at(Oj, rb_intern("Error")), "Unexpected type %02x.", leaf->type);
rb_raise(rb_const_get_at(Oj, rb_intern("Error")), "Unexpected type %02x.", leaf->rtype);
break;
}
}
Expand Down Expand Up @@ -348,79 +350,11 @@ leaf_fixnum_value(Leaf leaf) {
leaf->value_type = RUBY_VAL;
}

#ifdef JRUBY_RUBY
static void
leaf_float_value(Leaf leaf) {
char *s = leaf->str;
int64_t n = 0;
long a = 0;
long div = 1;
long e = 0;
int neg = 0;
int eneg = 0;
int big = 0;

if ('-' == *s) {
s++;
neg = 1;
} else if ('+' == *s) {
s++;
}
for (; '0' <= *s && *s <= '9'; s++) {
n = n * 10 + (*s - '0');
if (NUM_MAX <= n) {
big = 1;
}
}
if (big) {
char c = *s;

*s = '\0';
leaf->value = rb_cstr_to_inum(leaf->str, 10, 0);
*s = c;
} else {
double d;

if ('.' == *s) {
s++;
for (; '0' <= *s && *s <= '9'; s++) {
a = a * 10 + (*s - '0');
div *= 10;
}
}
if ('e' == *s || 'E' == *s) {
s++;
if ('-' == *s) {
s++;
eneg = 1;
} else if ('+' == *s) {
s++;
}
for (; '0' <= *s && *s <= '9'; s++) {
e = e * 10 + (*s - '0');
}
}
d = (double)n + (double)a / (double)div;
if (neg) {
d = -d;
}
if (0 != e) {
if (eneg) {
e = -e;
}
d *= pow(10.0, e);
}
leaf->value = rb_float_new(d);
}
leaf->value_type = RUBY_VAL;
}
#else
static void
leaf_float_value(Leaf leaf) {
leaf->value = rb_float_new(rb_cstr_to_dbl(leaf->str, 1));
leaf->value_type = RUBY_VAL;
}
#endif

static VALUE
leaf_array_value(Doc doc, Leaf leaf) {
Expand Down Expand Up @@ -732,6 +666,7 @@ read_quoted_value(ParseInfo pi) {
case '/': *t = '/'; break;
case '\\': *t = '\\'; break;
case 'u':
// TBD like parse.c, can use up to 6 characters
h++;
*t = read_hex(pi, h);
h += 2;
Expand Down Expand Up @@ -759,15 +694,10 @@ read_quoted_value(ParseInfo pi) {
// doc support functions
inline static void
doc_init(Doc doc) {
memset(doc, 0, sizeof(struct _Doc));
doc->where = doc->where_path;
*doc->where = 0;
doc->data = 0;
doc->self = Qundef;
doc->size = 0;
doc->json = 0;
doc->batches = &doc->batch0;
doc->batch0.next = 0;
doc->batch0.next_avail = 0;
}

static void
Expand Down Expand Up @@ -885,7 +815,7 @@ get_doc_leaf(Doc doc, const char *path) {
if (MAX_STACK <= cnt) {
rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
}
memcpy(stack, doc->where_path, sizeof(Leaf) * cnt);
memcpy(stack, doc->where_path, sizeof(Leaf) * (cnt + 1));
lp = stack + cnt;
}
return get_leaf(stack, lp, path);
Expand Down Expand Up @@ -914,7 +844,7 @@ get_leaf(Leaf *stack, Leaf *lp, const char *path) {
} else if (COL_VAL == leaf->value_type && 0 != leaf->elements) {
Leaf first = leaf->elements->next;
Leaf e = first;
int type = leaf->type;
int type = leaf->rtype;

leaf = 0;
if (T_ARRAY == type) {
Expand Down Expand Up @@ -1021,7 +951,7 @@ move_step(Doc doc, const char *path, int loc) {
Leaf first = leaf->elements->next;
Leaf e = first;

if (T_ARRAY == leaf->type) {
if (T_ARRAY == leaf->rtype) {
int cnt = 0;

for (; '0' <= *path && *path <= '9'; path++) {
Expand All @@ -1046,7 +976,7 @@ move_step(Doc doc, const char *path, int loc) {
cnt--;
e = e->next;
} while (e != first);
} else if (T_HASH == leaf->type) {
} else if (T_HASH == leaf->rtype) {
const char *key = path;
const char *slash = strchr(path, '/');
int klen;
Expand Down Expand Up @@ -1302,7 +1232,7 @@ doc_type(int argc, VALUE *argv, VALUE self) {
path = StringValuePtr(*argv);
}
if (0 != (leaf = get_doc_leaf(doc, path))) {
switch (leaf->type) {
switch (leaf->rtype) {
case T_NIL: type = rb_cNilClass; break;
case T_TRUE: type = rb_cTrueClass; break;
case T_FALSE: type = rb_cFalseClass; break;
Expand Down Expand Up @@ -1375,7 +1305,7 @@ doc_each_leaf(int argc, VALUE *argv, VALUE self) {

wlen = doc->where - doc->where_path;
if (0 < wlen) {
memcpy(save_path, doc->where_path, sizeof(Leaf) * wlen);
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
}
if (1 <= argc) {
Check_Type(*argv, T_STRING);
Expand All @@ -1386,14 +1316,14 @@ doc_each_leaf(int argc, VALUE *argv, VALUE self) {
}
if (0 != move_step(doc, path, 1)) {
if (0 < wlen) {
memcpy(doc->where_path, save_path, sizeof(Leaf) * wlen);
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
}
return Qnil;
}
}
each_leaf(doc, self);
if (0 < wlen) {
memcpy(doc->where_path, save_path, sizeof(Leaf) * wlen);
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
}
}
return Qnil;
Expand Down Expand Up @@ -1451,7 +1381,7 @@ doc_each_child(int argc, VALUE *argv, VALUE self) {

wlen = doc->where - doc->where_path;
if (0 < wlen) {
memcpy(save_path, doc->where_path, sizeof(Leaf) * wlen);
memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
}
if (1 <= argc) {
Check_Type(*argv, T_STRING);
Expand All @@ -1462,7 +1392,7 @@ doc_each_child(int argc, VALUE *argv, VALUE self) {
}
if (0 != move_step(doc, path, 1)) {
if (0 < wlen) {
memcpy(doc->where_path, save_path, sizeof(Leaf) * wlen);
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
}
return Qnil;
}
Expand All @@ -1479,7 +1409,7 @@ doc_each_child(int argc, VALUE *argv, VALUE self) {
} while (e != first);
}
if (0 < wlen) {
memcpy(doc->where_path, save_path, sizeof(Leaf) * wlen);
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
}
}
return Qnil;
Expand Down
11 changes: 6 additions & 5 deletions ext/oj/oj.h
Expand Up @@ -179,9 +179,10 @@ typedef struct _StreamWriter {
} *StreamWriter;

enum {
STR_VAL = 0x00,
COL_VAL = 0x01,
RUBY_VAL = 0x02
NO_VAL = 0x00,
STR_VAL = 0x01,
COL_VAL = 0x02,
RUBY_VAL = 0x03
};

typedef struct _Leaf {
Expand All @@ -191,11 +192,11 @@ typedef struct _Leaf {
size_t index; // array index, 0 is not set
};
union {
char *str; // pointer to location in json string
char *str; // pointer to location in json string or allocated
struct _Leaf *elements; // array and hash elements
VALUE value;
};
uint8_t type;
uint8_t rtype;
uint8_t parent_type;
uint8_t value_type;
} *Leaf;
Expand Down
2 changes: 1 addition & 1 deletion lib/oj/version.rb
@@ -1,5 +1,5 @@

module Oj
# Current version of the module.
VERSION = '2.12.1'
VERSION = '2.12.2a1'
end
4 changes: 3 additions & 1 deletion notes
Expand Up @@ -3,7 +3,9 @@
^c^d hide subtree
^c^s show subtree


- Oj::Doc
- make sure encoding handles encoding
- if \\u then create buf allocate

- streaming parser for scp and saj

Expand Down

0 comments on commit 10a4af8

Please sign in to comment.