ruby-changes:63109
From: Jean <ko1@a...>
Date: Fri, 25 Sep 2020 17:29:02 +0900 (JST)
Subject: [ruby-changes:63109] e1659af372 (master): Add an option to escape forward slash character
https://git.ruby-lang.org/ruby.git/commit/?id=e1659af372 From e1659af3724e2320e9f2f2bd7cf602686e8aa523 Mon Sep 17 00:00:00 2001 From: Jean Boussier <jean.boussier@g...> Date: Thu, 30 Jan 2020 12:48:05 +0100 Subject: Add an option to escape forward slash character Squashed commit of the following: commit 26d181059989279a79c433cedcd893b4f52e42ee Author: Francois Chagnon <francois.chagnon@j...> Date: Tue Sep 15 21:17:34 2015 +0000 add config options for escape_slash commit fa282334051b16df91ca097dd7304b46f3bc7719 Author: Francois Chagnon <francois.chagnon@j...> Date: Mon Feb 9 21:09:33 2015 +0000 add forward slash to escape character diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 749efaf..80d1ca7 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -22,7 +22,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L22 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_buffer_initial_length, i_dup; + i_buffer_initial_length, i_dup, i_escape_slash; /* * Copyright 2001-2004 Unicode, Inc. @@ -130,7 +130,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L130 /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII * 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 *sourceEnd = source + RSTRING_LEN(string); @@ -180,6 +180,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L180 case '"': fbuffer_append(buffer, "\\\"", 2); break; + case '/': + if(escape_slash) { + fbuffer_append(buffer, "\\/", 2); + break; + } default: fbuffer_append_char(buffer, (char)ch); break; @@ -229,7 +234,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L234 * characters required by the JSON standard are JSON escaped. The remaining * characters (should be UTF8) are just passed through and appended to the * 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; unsigned long len = RSTRING_LEN(string), start = 0, end = 0; @@ -280,6 +285,12 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L285 escape = "\\\""; escape_len = 2; break; + case '/': + if(escape_slash) { + escape = "\\/"; + escape_len = 2; + break; + } default: { unsigned short clen = 1; @@ -716,6 +727,8 @@ static VALUE cState_configure(VALUE self, VALUE opts) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L727 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_escape_slash)); + state->escape_slash = RTEST(tmp); return self; } @@ -750,6 +763,7 @@ static VALUE cState_to_h(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L763 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_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_buffer_initial_length), LONG2FIX(state->buffer_initial_length)); return result; @@ -934,9 +948,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L948 } #endif if (state->ascii_only) { - convert_UTF8_to_JSON_ASCII(buffer, obj); + convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash); } else { - convert_UTF8_to_JSON(buffer, obj); + convert_UTF8_to_JSON(buffer, obj, state->escape_slash); } fbuffer_append_char(buffer, '"'); } @@ -1378,6 +1392,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L1392 } /* + * 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? * * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise @@ -1489,6 +1528,9 @@ void Init_generator(void) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L1528 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_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, "allow_nan?", cState_allow_nan_p, 0); rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0); @@ -1545,6 +1587,7 @@ void Init_generator(void) https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.c#L1587 i_object_nl = rb_intern("object_nl"); i_array_nl = rb_intern("array_nl"); i_max_nesting = rb_intern("max_nesting"); + i_escape_slash = rb_intern("escape_slash"); i_allow_nan = rb_intern("allow_nan"); i_ascii_only = rb_intern("ascii_only"); i_depth = rb_intern("depth"); diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h index c367a62..3ebd622 100644 --- a/ext/json/generator/generator.h +++ b/ext/json/generator/generator.h @@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL; https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.h#L49 static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length); static void unicode_escape(char *buf, 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(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, char escape_slash); static char *fstrndup(const char *ptr, unsigned long len); /* ruby api and some helpers */ @@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct { https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.h#L72 long max_nesting; char allow_nan; char ascii_only; + char escape_slash; long depth; long buffer_initial_length; } JSON_Generator_State; @@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self); https://github.com/ruby/ruby/blob/trunk/ext/json/generator/generator.h#L151 static VALUE cState_ascii_only_p(VALUE self); static VALUE cState_depth(VALUE self); 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); #ifndef ZALLOC #define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type))) diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 991d760..8e45b51 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -593,12 +593,13 @@ module JSON https://github.com/ruby/ruby/blob/trunk/ext/json/lib/json/common.rb#L593 # Sets or returns the default options for the JSON.dump method. # Initially: # 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 end self.dump_default_options = { :max_nesting => false, :allow_nan => true, + :escape_slash => false, } # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb old mode 100644 new mode 100755 i (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/