Skip to content
Browse files

added class_cache option

  • Loading branch information...
1 parent 6bc4f37 commit 00f2666874bc4119a3449e87b93cdf37af9e532f @ohler55 committed Apr 22, 2013
Showing with 67 additions and 30 deletions.
  1. +38 −29 ext/oj/load.c
  2. +8 −0 ext/oj/oj.c
  3. +1 −0 ext/oj/oj.h
  4. +2 −1 notes
  5. +18 −0 test/tests.rb
View
67 ext/oj/load.c
@@ -159,43 +159,52 @@ classname2obj(const char *name, ParseInfo pi) {
}
static VALUE
+resolve_classpath(const char *name, ParseInfo pi) {
+ char class_name[1024];
+ VALUE clas;
+ int auto_define = (Yes == pi->options->auto_define);
+ char *end = class_name + sizeof(class_name) - 1;
+ char *s;
+ const char *n = name;
+
+ clas = rb_cObject;
+ for (s = class_name; '\0' != *n; n++) {
+ if (':' == *n) {
+ *s = '\0';
+ n++;
+ if (':' != *n) {
+ raise_error("Invalid classname, expected another ':'", pi->str, pi->s);
+ }
+ if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf) - 1, "Class %s not defined", class_name);
+ raise_error(buf, pi->str, pi->s);
+ }
+ s = class_name;
+ } else if (end <= s) {
+ raise_error("Invalid classname, limit is 1024 characters", pi->str, pi->s);
+ } else {
+ *s++ = *n;
+ }
+ }
+ *s = '\0';
+ return resolve_classname(clas, class_name, auto_define);
+}
+
+static VALUE
classname2class(const char *name, ParseInfo pi) {
VALUE clas;
VALUE *slot;
- int auto_define = (Yes == pi->options->auto_define);
+ if (No == pi->options->class_cache) {
+ return resolve_classpath(name, pi);
+ }
#if SAFE_CACHE
pthread_mutex_lock(&oj_cache_mutex);
#endif
if (Qundef == (clas = oj_cache_get(oj_class_cache, name, &slot))) {
- char class_name[1024];
- char *end = class_name + sizeof(class_name) - 1;
- char *s;
- const char *n = name;
-
- clas = rb_cObject;
- for (s = class_name; '\0' != *n; n++) {
- if (':' == *n) {
- *s = '\0';
- n++;
- if (':' != *n) {
- raise_error("Invalid classname, expected another ':'", pi->str, pi->s);
- }
- if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
- char buf[1024];
-
- snprintf(buf, sizeof(buf) - 1, "Class %s not defined", class_name);
- raise_error(buf, pi->str, pi->s);
- }
- s = class_name;
- } else if (end <= s) {
- raise_error("Invalid classname, limit is 1024 characters", pi->str, pi->s);
- } else {
- *s++ = *n;
- }
- }
- *s = '\0';
- if (Qundef != (clas = resolve_classname(clas, class_name, auto_define))) {
+ if (Qundef != (clas = resolve_classpath(name, pi))) {
*slot = clas;
}
}
View
8 ext/oj/oj.c
@@ -87,6 +87,7 @@ static VALUE auto_define_sym;
static VALUE bigdecimal_as_decimal_sym;
static VALUE bigdecimal_load_sym;
static VALUE circular_sym;
+static VALUE class_cache_sym;
static VALUE compat_sym;
static VALUE create_id_sym;
static VALUE indent_sym;
@@ -130,6 +131,7 @@ struct _Options oj_default_options = {
No, // sym_key
No, // ascii_only
ObjectMode, // mode
+ Yes, // class_cache
UnixTime, // time_format
Yes, // bigdec_as_num
No, // bigdec_load
@@ -161,6 +163,7 @@ oj_get_odd(VALUE clas) {
* - circular: [true|false|nil] support circular references while dumping
* - auto_define: [true|false|nil] automatically define classes if they do not exist
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
+ * - class_cache: [true|false|nil] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
* - time_format: [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
* - bigdecimal_as_decimal: [true|false|nil] dump BigDecimal as a decimal number or as a String
@@ -178,6 +181,7 @@ get_def_opts(VALUE self) {
rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
rb_hash_aset(opts, max_stack_sym, INT2FIX(oj_default_options.max_stack));
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
+ rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
rb_hash_aset(opts, auto_define_sym, (Yes == oj_default_options.auto_define) ? Qtrue : ((No == oj_default_options.auto_define) ? Qfalse : Qnil));
rb_hash_aset(opts, ascii_only_sym, (Yes == oj_default_options.ascii_only) ? Qtrue : ((No == oj_default_options.ascii_only) ? Qfalse : Qnil));
rb_hash_aset(opts, symbol_keys_sym, (Yes == oj_default_options.sym_key) ? Qtrue : ((No == oj_default_options.sym_key) ? Qfalse : Qnil));
@@ -209,6 +213,7 @@ get_def_opts(VALUE self) {
* @param [true|false|nil] :circular support circular references while dumping
* @param [true|false|nil] :auto_define automatically define classes if they do not exist
* @param [true|false|nil] :symbol_keys convert hash keys to symbols
+ * @param [true|false|nil] :class_cache cache classes for faster parsing
* @param [true|false|nil] :ascii_only encode all high-bit characters as escaped sequences if true
* @param [true|false|nil] :bigdecimal_as_decimal dump BigDecimal as a decimal number or as a String
* @param [true|false|nil] :bigdecimal_load load decimals as a BigDecimal instead of as a Float
@@ -235,6 +240,7 @@ set_def_opts(VALUE self, VALUE opts) {
{ circular_sym, &oj_default_options.circular },
{ auto_define_sym, &oj_default_options.auto_define },
{ symbol_keys_sym, &oj_default_options.sym_key },
+ { class_cache_sym, &oj_default_options.class_cache },
{ ascii_only_sym, &oj_default_options.ascii_only },
{ bigdecimal_as_decimal_sym, &oj_default_options.bigdec_as_num },
{ bigdecimal_load_sym, &oj_default_options.bigdec_load },
@@ -341,6 +347,7 @@ parse_options(VALUE ropts, Options copts) {
{ circular_sym, &copts->circular },
{ auto_define_sym, &copts->auto_define },
{ symbol_keys_sym, &copts->sym_key },
+ { class_cache_sym, &copts->class_cache },
{ ascii_only_sym, &copts->ascii_only },
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
{ bigdecimal_load_sym, &copts->bigdec_load },
@@ -1090,6 +1097,7 @@ void Init_oj() {
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));rb_gc_register_address(&bigdecimal_load_sym);
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
+ class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
View
1 ext/oj/oj.h
@@ -108,6 +108,7 @@ typedef struct _Options {
char sym_key; // YesNo
char ascii_only; // YesNo
char mode; // Mode
+ char class_cache; // YesNo
char time_format; // TimeFormat
char bigdec_as_num; // YesNo
char bigdec_load; // YesNo
View
3 notes
@@ -3,7 +3,8 @@
^c^d hide subtree
^c^s show subtree
-- add option to avoid class caching
++ fixed mimic issue with debian
++ add option to avoid class caching
- can dump be smarter about floats
- print for time when zulu
View
18 test/tests.rb
@@ -114,6 +114,7 @@ def test0_get_options
:circular=>false,
:auto_define=>false,
:symbol_keys=>false,
+ :class_cache=>true,
:ascii_only=>false,
:mode=>:object,
:time_format=>:unix,
@@ -130,6 +131,7 @@ def test0_set_options
:circular=>false,
:auto_define=>false,
:symbol_keys=>false,
+ :class_cache=>true,
:ascii_only=>false,
:mode=>:object,
:time_format=>:unix,
@@ -143,6 +145,7 @@ def test0_set_options
:circular=>true,
:auto_define=>true,
:symbol_keys=>true,
+ :class_cache=>false,
:ascii_only=>true,
:mode=>:compat,
:time_format=>:ruby,
@@ -641,6 +644,21 @@ def test_object_object
assert_equal(obj, obj2)
end
+ def test_object_object_no_cache
+ obj = Jam.new(true, 58)
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
+ assert(%{{
+ "^o":"Jam",
+ "x":true,
+ "y":58}} == json ||
+%{{
+ "^o":"Jam",
+ "y":58,
+ "x":true}} == json)
+ obj2 = Oj.load(json, :mode => :object, :class_cache => false)
+ assert_equal(obj, obj2)
+ end
+
# Exception
def test_exception
err = nil

0 comments on commit 00f2666

Please sign in to comment.
Something went wrong with that request. Please try again.