summaryrefslogtreecommitdiff
path: root/ext/json/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/ext')
-rw-r--r--ext/json/ext/generator/generator.c71
-rw-r--r--ext/json/ext/parser/parser.c205
-rw-r--r--ext/json/ext/parser/parser.rl30
3 files changed, 212 insertions, 94 deletions
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 1f48d3c780..108e80fd65 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -1,8 +1,33 @@
#include <string.h>
#include "ruby.h"
+#if HAVE_RUBY_ST_H
+#include "ruby/st.h"
+#endif
+#if HAVE_ST_H
+#include "st.h"
+#endif
#include "unicode.h"
#include <math.h>
+#ifndef RHASH_TBL
+#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
+#endif
+
+#ifndef RHASH_SIZE
+#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
+#endif
+
+#ifndef RFLOAT_VALUE
+#define RFLOAT_VALUE(val) (RFLOAT(val)->value)
+#endif
+
+#ifdef HAVE_RUBY_ENCODING_H
+#include "ruby/encoding.h"
+#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
+#else
+#define FORCE_UTF8(obj)
+#endif
+
#define check_max_nesting(state, depth) do { \
long current_nesting = 1 + depth; \
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@@ -163,6 +188,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
}
}
OBJ_INFECT(result, self);
+ FORCE_UTF8(result);
return result;
}
@@ -260,6 +286,7 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
result = mArray_json_transfrom(self, Vstate, Vdepth);
}
OBJ_INFECT(result, self);
+ FORCE_UTF8(result);
return result;
}
@@ -270,7 +297,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
*/
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
{
- return rb_funcall(self, i_to_s, 0);
+ VALUE result = rb_funcall(self, i_to_s, 0);
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -281,27 +310,29 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
{
JSON_Generator_State *state = NULL;
- VALUE Vstate, rest, tmp;
+ VALUE Vstate, rest, tmp, result;
double value = RFLOAT_VALUE(self);
rb_scan_args(argc, argv, "01*", &Vstate, &rest);
if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
if (isinf(value)) {
if (!state || state->allow_nan) {
- return rb_funcall(self, i_to_s, 0);
+ result = rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else if (isnan(value)) {
if (!state || state->allow_nan) {
- return rb_funcall(self, i_to_s, 0);
+ result = rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else {
- return rb_funcall(self, i_to_s, 0);
+ result = rb_funcall(self, i_to_s, 0);
}
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -310,7 +341,9 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
* Extends _modul_ with the String::Extend module.
*/
static VALUE mString_included_s(VALUE self, VALUE modul) {
- return rb_funcall(modul, i_extend, 1, mString_Extend);
+ VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -326,6 +359,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
rb_str_buf_cat2(result, "\"");
JSON_convert_UTF8_to_JSON(result, self, strictConversion);
rb_str_buf_cat2(result, "\"");
+ FORCE_UTF8(result);
return result;
}
@@ -343,6 +377,7 @@ static VALUE mString_to_json_raw_object(VALUE self) {
rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
rb_hash_aset(result, rb_str_new2("raw"), ary);
+ FORCE_UTF8(result);
return result;
}
@@ -353,9 +388,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
* to_json_raw_object of this String.
*/
static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
- VALUE obj = mString_to_json_raw_object(self);
+ VALUE result, obj = mString_to_json_raw_object(self);
Check_Type(obj, T_HASH);
- return mHash_to_json(argc, argv, obj);
+ result = mHash_to_json(argc, argv, obj);
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -378,7 +415,9 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
*/
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
{
- return rb_str_new2("true");
+ VALUE result = rb_str_new2("true");
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -388,7 +427,9 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
{
- return rb_str_new2("false");
+ VALUE result = rb_str_new2("false");
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -397,7 +438,9 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
{
- return rb_str_new2("null");
+ VALUE result = rb_str_new2("null");
+ FORCE_UTF8(result);
+ return result;
}
/*
@@ -409,9 +452,11 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
{
- VALUE string = rb_funcall(self, i_to_s, 0);
+ VALUE result, string = rb_funcall(self, i_to_s, 0);
Check_Type(string, T_STRING);
- return mString_to_json(argc, argv, string);
+ result = mString_to_json(argc, argv, string);
+ FORCE_UTF8(result);
+ return result;
}
/*
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 9de618d0e6..6928eda9e5 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -1,10 +1,30 @@
+
#line 1 "parser.rl"
#include "ruby.h"
-#include "ruby/encoding.h"
#include "unicode.h"
+#if HAVE_RE_H
+#include "re.h"
+#endif
+#if HAVE_RUBY_ST_H
+#include "ruby/st.h"
+#endif
+#if HAVE_ST_H
+#include "st.h"
+#endif
#define EVIL 0x666
+#ifndef RHASH_TBL
+#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
+#endif
+
+#ifdef HAVE_RUBY_ENCODING_H
+#include "ruby/encoding.h"
+#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
+#else
+#define FORCE_UTF8(obj)
+#endif
+
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
static VALUE CNaN, CInfinity, CMinusInfinity;
@@ -35,18 +55,20 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
JSON_Parser *json; \
Data_Get_Struct(self, JSON_Parser, json);
-#line 64 "parser.rl"
+#line 82 "parser.rl"
-#line 44 "parser.c"
+
+#line 64 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 97 "parser.rl"
+
+#line 115 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -61,13 +83,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_hash_new();
-#line 66 "parser.c"
+#line 87 "parser.c"
{
cs = JSON_object_start;
}
-#line 111 "parser.rl"
+
+#line 129 "parser.rl"
-#line 72 "parser.c"
+#line 94 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -95,7 +118,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 83 "parser.rl"
+#line 101 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, &last_name);
if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;}
@@ -105,7 +128,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 110 "parser.c"
+#line 132 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -172,7 +195,7 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 72 "parser.rl"
+#line 90 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -188,7 +211,7 @@ st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 193 "parser.c"
+#line 215 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -277,14 +300,14 @@ case 18:
goto st9;
goto st18;
tr4:
-#line 88 "parser.rl"
+#line 106 "parser.rl"
{ p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
goto _test_eof27;
case 27:
-#line 289 "parser.c"
+#line 311 "parser.c"
goto st0;
st19:
if ( ++p == pe )
@@ -381,7 +404,8 @@ case 26:
_test_eof: {}
_out: {}
}
-#line 112 "parser.rl"
+
+#line 130 "parser.rl"
if (cs >= JSON_object_first_final) {
if (RTEST(json->create_id)) {
@@ -400,14 +424,15 @@ case 26:
}
-#line 405 "parser.c"
+#line 428 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 210 "parser.rl"
+
+#line 228 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -415,13 +440,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 420 "parser.c"
+#line 444 "parser.c"
{
cs = JSON_value_start;
}
-#line 217 "parser.rl"
+
+#line 235 "parser.rl"
-#line 426 "parser.c"
+#line 451 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -446,14 +472,14 @@ st0:
cs = 0;
goto _out;
tr0:
-#line 158 "parser.rl"
+#line 176 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr2:
-#line 163 "parser.rl"
+#line 181 "parser.rl"
{
char *np;
if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) {
@@ -473,7 +499,7 @@ tr2:
}
goto st21;
tr5:
-#line 181 "parser.rl"
+#line 199 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -483,7 +509,7 @@ tr5:
}
goto st21;
tr9:
-#line 189 "parser.rl"
+#line 207 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -493,7 +519,7 @@ tr9:
}
goto st21;
tr16:
-#line 151 "parser.rl"
+#line 169 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
@@ -503,7 +529,7 @@ tr16:
}
goto st21;
tr18:
-#line 144 "parser.rl"
+#line 162 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
@@ -513,19 +539,19 @@ tr18:
}
goto st21;
tr22:
-#line 138 "parser.rl"
+#line 156 "parser.rl"
{
*result = Qfalse;
}
goto st21;
tr25:
-#line 135 "parser.rl"
+#line 153 "parser.rl"
{
*result = Qnil;
}
goto st21;
tr28:
-#line 141 "parser.rl"
+#line 159 "parser.rl"
{
*result = Qtrue;
}
@@ -534,9 +560,9 @@ st21:
if ( ++p == pe )
goto _test_eof21;
case 21:
-#line 197 "parser.rl"
+#line 215 "parser.rl"
{ p--; {p++; cs = 21; goto _out;} }
-#line 541 "parser.c"
+#line 566 "parser.c"
goto st0;
st2:
if ( ++p == pe )
@@ -696,7 +722,8 @@ case 20:
_test_eof: {}
_out: {}
}
-#line 218 "parser.rl"
+
+#line 236 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -706,14 +733,15 @@ case 20:
}
-#line 711 "parser.c"
+#line 737 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 5;
static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 234 "parser.rl"
+
+#line 252 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -721,14 +749,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 726 "parser.c"
+#line 753 "parser.c"
{
cs = JSON_integer_start;
}
-#line 241 "parser.rl"
+
+#line 259 "parser.rl"
json->memo = p;
-#line 733 "parser.c"
+#line 761 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -762,14 +791,14 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 231 "parser.rl"
+#line 249 "parser.rl"
{ p--; {p++; cs = 5; goto _out;} }
goto st5;
st5:
if ( ++p == pe )
goto _test_eof5;
case 5:
-#line 774 "parser.c"
+#line 802 "parser.c"
goto st0;
st4:
if ( ++p == pe )
@@ -787,7 +816,8 @@ case 4:
_test_eof: {}
_out: {}
}
-#line 243 "parser.rl"
+
+#line 261 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -799,14 +829,15 @@ case 4:
}
-#line 804 "parser.c"
+#line 833 "parser.c"
static const int JSON_float_start = 1;
static const int JSON_float_first_final = 10;
static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 265 "parser.rl"
+
+#line 283 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -814,14 +845,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 819 "parser.c"
+#line 849 "parser.c"
{
cs = JSON_float_start;
}
-#line 272 "parser.rl"
+
+#line 290 "parser.rl"
json->memo = p;
-#line 826 "parser.c"
+#line 857 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -879,14 +911,14 @@ case 5:
goto st0;
goto tr7;
tr7:
-#line 259 "parser.rl"
+#line 277 "parser.rl"
{ p--; {p++; cs = 10; goto _out;} }
goto st10;
st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 891 "parser.c"
+#line 922 "parser.c"
goto st0;
st6:
if ( ++p == pe )
@@ -946,7 +978,8 @@ case 9:
_test_eof: {}
_out: {}
}
-#line 274 "parser.rl"
+
+#line 292 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -959,14 +992,15 @@ case 9:
-#line 964 "parser.c"
+#line 996 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 310 "parser.rl"
+
+#line 328 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -979,13 +1013,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = rb_ary_new();
-#line 984 "parser.c"
+#line 1017 "parser.c"
{
cs = JSON_array_start;
}
-#line 322 "parser.rl"
+
+#line 340 "parser.rl"
-#line 990 "parser.c"
+#line 1024 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1024,7 +1059,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 291 "parser.rl"
+#line 309 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -1040,7 +1075,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 1045 "parser.c"
+#line 1079 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1140,14 +1175,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 302 "parser.rl"
+#line 320 "parser.rl"
{ p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
goto _test_eof17;
case 17:
-#line 1152 "parser.c"
+#line 1186 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1202,7 +1237,8 @@ case 16:
_test_eof: {}
_out: {}
}
-#line 323 "parser.rl"
+
+#line 341 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1268,14 +1304,15 @@ static VALUE json_string_unescape(char *p, char *pe)
}
-#line 1273 "parser.c"
+#line 1308 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 401 "parser.rl"
+
+#line 425 "parser.rl"
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1284,14 +1321,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_new("", 0);
-#line 1289 "parser.c"
+#line 1325 "parser.c"
{
cs = JSON_string_start;
}
-#line 409 "parser.rl"
+
+#line 433 "parser.rl"
json->memo = p;
-#line 1296 "parser.c"
+#line 1333 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1316,19 +1354,25 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 393 "parser.rl"
+#line 411 "parser.rl"
{
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) { p--; {p++; cs = 8; goto _out;} } else {p = (( p + 1))-1;}
- }
-#line 398 "parser.rl"
+ if (NIL_P(*result)) {
+ p--;
+ {p++; cs = 8; goto _out;}
+ } else {
+ FORCE_UTF8(*result);
+ {p = (( p + 1))-1;}
+ }
+ }
+#line 422 "parser.rl"
{ p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
-#line 1333 "parser.c"
+#line 1376 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1403,11 +1447,11 @@ case 7:
_test_eof: {}
_out: {}
}
-#line 411 "parser.rl"
+
+#line 435 "parser.rl"
if (cs >= JSON_string_first_final) {
- rb_enc_associate(*result, rb_utf8_encoding());
- return p + 1;
+ return p + 1;
} else {
return NULL;
}
@@ -1415,14 +1459,15 @@ case 7:
-#line 1419 "parser.c"
+#line 1463 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 445 "parser.rl"
+
+#line 469 "parser.rl"
/*
@@ -1545,15 +1590,16 @@ static VALUE cParser_parse(VALUE self)
GET_STRUCT;
-#line 1549 "parser.c"
+#line 1594 "parser.c"
{
cs = JSON_start;
}
-#line 567 "parser.rl"
+
+#line 591 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1557 "parser.c"
+#line 1603 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1609,7 +1655,7 @@ case 5:
goto st1;
goto st5;
tr3:
-#line 434 "parser.rl"
+#line 458 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1618,7 +1664,7 @@ tr3:
}
goto st10;
tr4:
-#line 427 "parser.rl"
+#line 451 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1630,7 +1676,7 @@ st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1634 "parser.c"
+#line 1680 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1686,7 +1732,8 @@ case 9:
_test_eof: {}
_out: {}
}
-#line 570 "parser.rl"
+
+#line 594 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index 8325a93795..ca1876a7fc 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -1,8 +1,28 @@
#include "ruby.h"
#include "unicode.h"
+#if HAVE_RE_H
+#include "re.h"
+#endif
+#if HAVE_RUBY_ST_H
+#include "ruby/st.h"
+#endif
+#if HAVE_ST_H
+#include "st.h"
+#endif
#define EVIL 0x666
+#ifndef RHASH_TBL
+#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
+#endif
+
+#ifdef HAVE_RUBY_ENCODING_H
+#include "ruby/encoding.h"
+#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
+#else
+#define FORCE_UTF8(obj)
+#endif
+
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
static VALUE CNaN, CInfinity, CMinusInfinity;
@@ -390,8 +410,14 @@ static VALUE json_string_unescape(char *p, char *pe)
action parse_string {
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) { fhold; fbreak; } else fexec p + 1;
- }
+ if (NIL_P(*result)) {
+ fhold;
+ fbreak;
+ } else {
+ FORCE_UTF8(*result);
+ fexec p + 1;
+ }
+ }
action exit { fhold; fbreak; }