Add an option to escape forward slash character
Squashed commit of the following: commit 26d181059989279a79c433cedcd893b4f52e42ee Author: Francois Chagnon <francois.chagnon@jadedpixel.com> Date: Tue Sep 15 21:17:34 2015 +0000 add config options for escape_slash commit fa282334051b16df91ca097dd7304b46f3bc7719 Author: Francois Chagnon <francois.chagnon@jadedpixel.com> Date: Mon Feb 9 21:09:33 2015 +0000 add forward slash to escape character
This commit is contained in:
parent
c5ea060ef8
commit
e1659af372
Notes:
git
2020-09-25 17:29:15 +09:00
@ -22,7 +22,7 @@ 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_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_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_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
||||||
i_buffer_initial_length, i_dup;
|
i_buffer_initial_length, i_dup, i_escape_slash;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2004 Unicode, Inc.
|
* Copyright 2001-2004 Unicode, Inc.
|
||||||
@ -130,7 +130,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|||||||
|
|
||||||
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
||||||
* and control characters are JSON escaped. */
|
* and control characters are JSON escaped. */
|
||||||
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
|
||||||
{
|
{
|
||||||
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
||||||
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
||||||
@ -180,6 +180,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|||||||
case '"':
|
case '"':
|
||||||
fbuffer_append(buffer, "\\\"", 2);
|
fbuffer_append(buffer, "\\\"", 2);
|
||||||
break;
|
break;
|
||||||
|
case '/':
|
||||||
|
if(escape_slash) {
|
||||||
|
fbuffer_append(buffer, "\\/", 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fbuffer_append_char(buffer, (char)ch);
|
fbuffer_append_char(buffer, (char)ch);
|
||||||
break;
|
break;
|
||||||
@ -229,7 +234,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|||||||
* characters required by the JSON standard are JSON escaped. The remaining
|
* characters required by the JSON standard are JSON escaped. The remaining
|
||||||
* characters (should be UTF8) are just passed through and appended to the
|
* characters (should be UTF8) are just passed through and appended to the
|
||||||
* result. */
|
* result. */
|
||||||
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
|
||||||
{
|
{
|
||||||
const char *ptr = RSTRING_PTR(string), *p;
|
const char *ptr = RSTRING_PTR(string), *p;
|
||||||
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
||||||
@ -280,6 +285,12 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|||||||
escape = "\\\"";
|
escape = "\\\"";
|
||||||
escape_len = 2;
|
escape_len = 2;
|
||||||
break;
|
break;
|
||||||
|
case '/':
|
||||||
|
if(escape_slash) {
|
||||||
|
escape = "\\/";
|
||||||
|
escape_len = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unsigned short clen = 1;
|
unsigned short clen = 1;
|
||||||
@ -716,6 +727,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|||||||
state->allow_nan = RTEST(tmp);
|
state->allow_nan = RTEST(tmp);
|
||||||
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
||||||
state->ascii_only = RTEST(tmp);
|
state->ascii_only = RTEST(tmp);
|
||||||
|
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
||||||
|
state->escape_slash = RTEST(tmp);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,6 +763,7 @@ static VALUE cState_to_h(VALUE self)
|
|||||||
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
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_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
||||||
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
||||||
|
rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
|
||||||
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
||||||
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
||||||
return result;
|
return result;
|
||||||
@ -934,9 +948,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (state->ascii_only) {
|
if (state->ascii_only) {
|
||||||
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
|
||||||
} else {
|
} else {
|
||||||
convert_UTF8_to_JSON(buffer, obj);
|
convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
|
||||||
}
|
}
|
||||||
fbuffer_append_char(buffer, '"');
|
fbuffer_append_char(buffer, '"');
|
||||||
}
|
}
|
||||||
@ -1377,6 +1391,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|||||||
return state->max_nesting = FIX2LONG(depth);
|
return state->max_nesting = FIX2LONG(depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq: escape_slash
|
||||||
|
*
|
||||||
|
* If this boolean is true, the forward slashes will be escaped in
|
||||||
|
* the json output.
|
||||||
|
*/
|
||||||
|
static VALUE cState_escape_slash(VALUE self)
|
||||||
|
{
|
||||||
|
GET_STATE(self);
|
||||||
|
return state->escape_slash ? Qtrue : Qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq: escape_slash=(depth)
|
||||||
|
*
|
||||||
|
* This sets whether or not the forward slashes will be escaped in
|
||||||
|
* the json output.
|
||||||
|
*/
|
||||||
|
static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
|
||||||
|
{
|
||||||
|
GET_STATE(self);
|
||||||
|
state->escape_slash = RTEST(enable);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq: allow_nan?
|
* call-seq: allow_nan?
|
||||||
*
|
*
|
||||||
@ -1489,6 +1528,9 @@ void Init_generator(void)
|
|||||||
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
||||||
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
||||||
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
||||||
|
rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
|
||||||
|
rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
|
||||||
|
rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
|
||||||
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
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, "allow_nan?", cState_allow_nan_p, 0);
|
||||||
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
||||||
@ -1545,6 +1587,7 @@ void Init_generator(void)
|
|||||||
i_object_nl = rb_intern("object_nl");
|
i_object_nl = rb_intern("object_nl");
|
||||||
i_array_nl = rb_intern("array_nl");
|
i_array_nl = rb_intern("array_nl");
|
||||||
i_max_nesting = rb_intern("max_nesting");
|
i_max_nesting = rb_intern("max_nesting");
|
||||||
|
i_escape_slash = rb_intern("escape_slash");
|
||||||
i_allow_nan = rb_intern("allow_nan");
|
i_allow_nan = rb_intern("allow_nan");
|
||||||
i_ascii_only = rb_intern("ascii_only");
|
i_ascii_only = rb_intern("ascii_only");
|
||||||
i_depth = rb_intern("depth");
|
i_depth = rb_intern("depth");
|
||||||
|
@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
|
|||||||
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
|
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
|
||||||
static void unicode_escape(char *buf, UTF16 character);
|
static void unicode_escape(char *buf, UTF16 character);
|
||||||
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
|
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
|
||||||
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
|
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
|
||||||
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
|
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
|
||||||
static char *fstrndup(const char *ptr, unsigned long len);
|
static char *fstrndup(const char *ptr, unsigned long len);
|
||||||
|
|
||||||
/* ruby api and some helpers */
|
/* ruby api and some helpers */
|
||||||
@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct {
|
|||||||
long max_nesting;
|
long max_nesting;
|
||||||
char allow_nan;
|
char allow_nan;
|
||||||
char ascii_only;
|
char ascii_only;
|
||||||
|
char escape_slash;
|
||||||
long depth;
|
long depth;
|
||||||
long buffer_initial_length;
|
long buffer_initial_length;
|
||||||
} JSON_Generator_State;
|
} JSON_Generator_State;
|
||||||
@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
|
|||||||
static VALUE cState_ascii_only_p(VALUE self);
|
static VALUE cState_ascii_only_p(VALUE self);
|
||||||
static VALUE cState_depth(VALUE self);
|
static VALUE cState_depth(VALUE self);
|
||||||
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
||||||
|
static VALUE cState_escape_slash(VALUE self);
|
||||||
|
static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
|
||||||
static FBuffer *cState_prepare_buffer(VALUE self);
|
static FBuffer *cState_prepare_buffer(VALUE self);
|
||||||
#ifndef ZALLOC
|
#ifndef ZALLOC
|
||||||
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|
||||||
|
@ -593,12 +593,13 @@ module JSON
|
|||||||
# Sets or returns the default options for the JSON.dump method.
|
# Sets or returns the default options for the JSON.dump method.
|
||||||
# Initially:
|
# Initially:
|
||||||
# opts = JSON.dump_default_options
|
# opts = JSON.dump_default_options
|
||||||
# opts # => {:max_nesting=>false, :allow_nan=>true}
|
# opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
|
||||||
attr_accessor :dump_default_options
|
attr_accessor :dump_default_options
|
||||||
end
|
end
|
||||||
self.dump_default_options = {
|
self.dump_default_options = {
|
||||||
:max_nesting => false,
|
:max_nesting => false,
|
||||||
:allow_nan => true,
|
:allow_nan => true,
|
||||||
|
:escape_slash => false,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
|
# Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
|
||||||
|
7
test/json/json_generator_test.rb
Normal file → Executable file
7
test/json/json_generator_test.rb
Normal file → Executable file
@ -174,6 +174,7 @@ EOT
|
|||||||
:ascii_only => false,
|
:ascii_only => false,
|
||||||
:buffer_initial_length => 1024,
|
:buffer_initial_length => 1024,
|
||||||
:depth => 0,
|
:depth => 0,
|
||||||
|
:escape_slash => false,
|
||||||
:indent => " ",
|
:indent => " ",
|
||||||
:max_nesting => 100,
|
:max_nesting => 100,
|
||||||
:object_nl => "\n",
|
:object_nl => "\n",
|
||||||
@ -190,6 +191,7 @@ EOT
|
|||||||
:ascii_only => false,
|
:ascii_only => false,
|
||||||
:buffer_initial_length => 1024,
|
:buffer_initial_length => 1024,
|
||||||
:depth => 0,
|
:depth => 0,
|
||||||
|
:escape_slash => false,
|
||||||
:indent => "",
|
:indent => "",
|
||||||
:max_nesting => 100,
|
:max_nesting => 100,
|
||||||
:object_nl => "",
|
:object_nl => "",
|
||||||
@ -206,6 +208,7 @@ EOT
|
|||||||
:ascii_only => false,
|
:ascii_only => false,
|
||||||
:buffer_initial_length => 1024,
|
:buffer_initial_length => 1024,
|
||||||
:depth => 0,
|
:depth => 0,
|
||||||
|
:escape_slash => false,
|
||||||
:indent => "",
|
:indent => "",
|
||||||
:max_nesting => 0,
|
:max_nesting => 0,
|
||||||
:object_nl => "",
|
:object_nl => "",
|
||||||
@ -394,6 +397,10 @@ EOT
|
|||||||
json = '["/"]'
|
json = '["/"]'
|
||||||
assert_equal json, generate(data)
|
assert_equal json, generate(data)
|
||||||
#
|
#
|
||||||
|
data = [ '/' ]
|
||||||
|
json = '["\/"]'
|
||||||
|
assert_equal json, generate(data, :escape_slash => true)
|
||||||
|
#
|
||||||
data = ['"']
|
data = ['"']
|
||||||
json = '["\""]'
|
json = '["\""]'
|
||||||
assert_equal json, generate(data)
|
assert_equal json, generate(data)
|
||||||
|
@ -293,6 +293,10 @@ EOT
|
|||||||
json = '["\\\'"]'
|
json = '["\\\'"]'
|
||||||
data = ["'"]
|
data = ["'"]
|
||||||
assert_equal data, parse(json)
|
assert_equal data, parse(json)
|
||||||
|
|
||||||
|
json = '["\/"]'
|
||||||
|
data = [ '/' ]
|
||||||
|
assert_equal data, parse(json)
|
||||||
end
|
end
|
||||||
|
|
||||||
class SubArray < Array
|
class SubArray < Array
|
||||||
|
Loading…
x
Reference in New Issue
Block a user