Skip to content

Commit

Permalink
started quirks mode for generator
Browse files Browse the repository at this point in the history
  • Loading branch information
flori committed Jul 27, 2011
1 parent 9320a2a commit bdb2b91
Show file tree
Hide file tree
Showing 16 changed files with 207 additions and 104 deletions.
47 changes: 40 additions & 7 deletions ext/json/ext/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,

static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
i_respond_to_p, i_match, i_keys, i_depth, i_dup;
i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth, i_dup;

/*
* Copyright 2001-2004 Unicode, Inc.
Expand Down Expand Up @@ -688,6 +688,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
state->allow_nan = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
state->ascii_only = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
state->quirks_mode = RTEST(tmp);
return self;
}

Expand All @@ -708,6 +710,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
return result;
Expand Down Expand Up @@ -961,11 +964,14 @@ static VALUE cState_generate(VALUE self, VALUE obj)
{
VALUE result = cState_partial_generate(self, obj);
VALUE re, args[2];
args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
args[1] = CRegexp_MULTILINE;
re = rb_class_new_instance(2, args, rb_cRegexp);
if (NIL_P(rb_funcall(re, i_match, 1, result))) {
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
GET_STATE(self);
if (!state->quirks_mode) {
args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
args[1] = CRegexp_MULTILINE;
re = rb_class_new_instance(2, args, rb_cRegexp);
if (NIL_P(rb_funcall(re, i_match, 1, result))) {
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
}
}
return result;
}
Expand Down Expand Up @@ -1287,6 +1293,29 @@ static VALUE cState_ascii_only_p(VALUE self)
return state->ascii_only ? Qtrue : Qfalse;
}

/*
* call-seq: quirks_mode?
*
* Returns true, if quirks mode is enabled. Otherwise returns false.
*/
static VALUE cState_quirks_mode_p(VALUE self)
{
GET_STATE(self);
return state->quirks_mode ? Qtrue : Qfalse;
}

/*
* call-seq: quirks_mode=(enable)
*
* If set to true, enables the quirks_mode mode.
*/
static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
{
GET_STATE(self);
state->quirks_mode = RTEST(enable);
return Qnil;
}

/*
* call-seq: depth
*
Expand Down Expand Up @@ -1345,6 +1374,9 @@ void Init_generator()
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
rb_define_method(cState, "depth", cState_depth, 0);
rb_define_method(cState, "depth=", cState_depth_set, 1);
rb_define_method(cState, "configure", cState_configure, 1);
Expand Down Expand Up @@ -1392,6 +1424,7 @@ void Init_generator()
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
i_quirks_mode = rb_intern("quirks_mode");
i_depth = rb_intern("depth");
i_pack = rb_intern("pack");
i_unpack = rb_intern("unpack");
Expand Down
1 change: 1 addition & 0 deletions ext/json/ext/generator/generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ typedef struct JSON_Generator_StateStruct {
long max_nesting;
char allow_nan;
char ascii_only;
char quirks_mode;
long depth;
} JSON_Generator_State;

Expand Down
6 changes: 3 additions & 3 deletions java/src/json/ext/Generator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
*
*
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
Expand Down Expand Up @@ -85,11 +85,11 @@ Handler<? super T> getHandlerFor(Ruby runtime, T object) {
/**
* A class that concentrates all the information that is shared by
* generators working on a single session.
*
*
* <p>A session is defined as the process of serializing a single root
* object; any handler directly called by container handlers (arrays and
* hashes/objects) shares this object with its caller.
*
*
* <p>Note that anything called indirectly (via {@link GENERIC_HANDLER})
* won't be part of the session.
*/
Expand Down
4 changes: 2 additions & 2 deletions java/src/json/ext/GeneratorMethods.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
*
*
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
Expand All @@ -25,7 +25,7 @@
/**
* A class that populates the
* <code>Json::Ext::Generator::GeneratorMethods</code> module.
*
*
* @author mernen
*/
class GeneratorMethods {
Expand Down
2 changes: 1 addition & 1 deletion java/src/json/ext/GeneratorService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
*
*
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
Expand Down
46 changes: 35 additions & 11 deletions java/src/json/ext/GeneratorState.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
*
*
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
Expand All @@ -24,10 +24,10 @@

/**
* The <code>JSON::Ext::Generator::State</code> class.
*
*
* <p>This class is used to create State instances, that are use to hold data
* while generating a JSON text from a a Ruby data structure.
*
*
* @author mernen
*/
public class GeneratorState extends RubyObject {
Expand Down Expand Up @@ -76,6 +76,11 @@ public class GeneratorState extends RubyObject {
*/
private boolean asciiOnly = DEFAULT_ASCII_ONLY;
static final boolean DEFAULT_ASCII_ONLY = false;
/**
* XXX
*/
private boolean quirksMode = DEFAULT_QUIRKS_MODE;
static final boolean DEFAULT_QUIRKS_MODE = false;

/**
* The current depth (inside a #to_json call)
Expand All @@ -94,7 +99,7 @@ public GeneratorState(Ruby runtime, RubyClass metaClass) {

/**
* <code>State.from_state(opts)</code>
*
*
* <p>Creates a State object from <code>opts</code>, which ought to be
* {@link RubyHash Hash} to create a new <code>State</code> instance
* configured by <codes>opts</code>, something else to create an
Expand Down Expand Up @@ -136,11 +141,11 @@ static GeneratorState fromState(ThreadContext context, RuntimeInfo info,

/**
* <code>State#initialize(opts = {})</code>
*
*
* Instantiates a new <code>State</code> object, configured by <code>opts</code>.
*
*
* <code>opts</code> can have the following keys:
*
*
* <dl>
* <dt><code>:indent</code>
* <dd>a {@link RubyString String} used to indent levels (default: <code>""</code>)
Expand All @@ -151,7 +156,7 @@ static GeneratorState fromState(ThreadContext context, RuntimeInfo info,
* <dd>a String that is put before a <code>":"</code> pair delimiter
* (default: <code>""</code>)
* <dt><code>:object_nl</code>
* <dd>a String that is put at the end of a JSON object (default: <code>""</code>)
* <dd>a String that is put at the end of a JSON object (default: <code>""</code>)
* <dt><code>:array_nl</code>
* <dd>a String that is put at the end of a JSON array (default: <code>""</code>)
* <dt><code>:allow_nan</code>
Expand Down Expand Up @@ -181,6 +186,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject vOrig) {
this.maxNesting = orig.maxNesting;
this.allowNaN = orig.allowNaN;
this.asciiOnly = orig.asciiOnly;
this.quirksMode = orig.quirksMode;
this.depth = orig.depth;
return this;
}
Expand All @@ -191,7 +197,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject vOrig) {
@JRubyMethod
public IRubyObject generate(ThreadContext context, IRubyObject obj) {
RubyString result = Generator.generateJson(context, obj, this);
if (!objectOrArrayLiteral(result)) {
if (!quirksMode && !objectOrArrayLiteral(result)) {
throw Utils.newException(context, Utils.M_GENERATOR_ERROR,
"only generation of JSON objects or arrays allowed");
}
Expand Down Expand Up @@ -364,6 +370,22 @@ public RubyBoolean ascii_only_p(ThreadContext context) {
return context.getRuntime().newBoolean(asciiOnly);
}

@JRubyMethod(name="quirks_mode")
public RubyBoolean quirks_mode_get(ThreadContext context) {
return context.getRuntime().newBoolean(quirksMode);
}

@JRubyMethod(name="quirks_mode=")
public IRubyObject quirks_mode_set(IRubyObject quirks_mode) {
quirksMode = quirks_mode.isTrue();
return quirks_mode.getRuntime().newBoolean(quirksMode);
}

@JRubyMethod(name="quirks_mode?")
public RubyBoolean quirks_mode_p(ThreadContext context) {
return context.getRuntime().newBoolean(quirksMode);
}

public int getDepth() {
return depth;
}
Expand All @@ -390,7 +412,7 @@ private ByteList prepareByteList(ThreadContext context, IRubyObject value) {

/**
* <code>State#configure(opts)</code>
*
*
* <p>Configures this State instance with the {@link RubyHash Hash}
* <code>opts</code>, and returns itself.
* @param vOpts The options hash
Expand Down Expand Up @@ -418,6 +440,7 @@ public IRubyObject configure(ThreadContext context, IRubyObject vOpts) {
maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN);
asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY);
quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE);

depth = opts.getInt("depth", 0);

Expand All @@ -426,7 +449,7 @@ public IRubyObject configure(ThreadContext context, IRubyObject vOpts) {

/**
* <code>State#to_h()</code>
*
*
* <p>Returns the configuration instance variables as a hash, that can be
* passed to the configure method.
* @return
Expand All @@ -443,6 +466,7 @@ public RubyHash to_h(ThreadContext context) {
result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context));
result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context));
result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context));
result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context));
result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context));
result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
return result;
Expand Down
2 changes: 1 addition & 1 deletion java/src/json/ext/OptionsReader.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
*
*
* Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
* for details.
*/
Expand Down
Loading

0 comments on commit bdb2b91

Please sign in to comment.