@@ -47,7 +47,7 @@ interface Jsonable
47
47
# avoid cyclic references between `append_json` and `to_json` when none are
48
48
# implemented.
49
49
protected fun to_json_by_append : String do
50
- var buffer = new RopeBuffer
50
+ var buffer = new FlatBuffer
51
51
append_json (buffer )
52
52
return buffer .to_s
53
53
end
89
89
redef class Text
90
90
super Jsonable
91
91
92
+ # Removes JSON-escaping if necessary in a JSON string
93
+ #
94
+ # assert "\\\"string\\uD83D\\uDE02\\\"".unescape_json == "\"string😂\""
95
+ fun unescape_json : Text do
96
+ if not json_need_escape then return self
97
+ return self .json_to_nit_string
98
+ end
99
+
100
+ # Does `self` need treatment from JSON to Nit ?
101
+ #
102
+ # i.e. is there at least one `\` character in it ?
103
+ #
104
+ # assert not "string".json_need_escape
105
+ # assert "\\\"string\\\"".json_need_escape
106
+ protected fun json_need_escape : Bool do return has ('\\' )
107
+
92
108
redef fun append_json (buffer ) do
93
109
buffer .add '\"'
94
110
for i in [0 .. self .length [ do
@@ -97,19 +113,13 @@ redef class Text
97
113
buffer .append "\\\\ "
98
114
else if char == '\"' then
99
115
buffer .append "\\\" "
100
- else if char == '\/' then
101
- buffer .append "\\/ "
102
116
else if char < ' ' then
103
117
if char == '\n' then
104
118
buffer .append "\\n "
105
119
else if char == '\r' then
106
120
buffer .append "\\r "
107
121
else if char == '\t' then
108
122
buffer .append "\\t "
109
- else if char == 0x0C .code_point then
110
- buffer .append "\\f "
111
- else if char == 0x08 .code_point then
112
- buffer .append "\\b "
113
123
else
114
124
buffer .append char .escape_to_utf16
115
125
end
@@ -120,13 +130,66 @@ redef class Text
120
130
buffer .add '\"'
121
131
end
122
132
133
+ # Escapes `self` from a JSON string to a Nit string
134
+ #
135
+ # assert "\\\"string\\\"".json_to_nit_string == "\"string\""
136
+ # assert "\\nEscape\\t\\n".json_to_nit_string == "\nEscape\t\n"
137
+ # assert "\\u0041zu\\uD800\\uDFD3".json_to_nit_string == "Azu𐏓"
138
+ protected fun json_to_nit_string : String do
139
+ var res = new FlatBuffer .with_capacity (bytelen )
140
+ var i = 0
141
+ while i < self .length do
142
+ var char = self [i ]
143
+ if char == '\\' then
144
+ i += 1
145
+ char = self [i ]
146
+ if char == 'b' then
147
+ char = 0x08 .code_point
148
+ else if char == 'f' then
149
+ char = 0x0C .code_point
150
+ else if char == 'n' then
151
+ char = '\n'
152
+ else if char == 'r' then
153
+ char = '\r'
154
+ else if char == 't' then
155
+ char = '\t'
156
+ else if char == 'u' then
157
+ var code = substring (i + 1 , 4 )
158
+ var hx = code .to_hex
159
+ if hx >= 0xD800 and hx <= 0xDFFF then
160
+ var lostr = substring (i + 7 , 4 )
161
+ if lostr .length < 4 then
162
+ hx = 0xFFFD
163
+ else
164
+ hx <<= 16
165
+ hx += lostr .to_hex
166
+ hx = hx .from_utf16_surr
167
+ end
168
+ i += 6
169
+ end
170
+ i += 4
171
+ char = hx .code_point
172
+ end
173
+ # `"`, `/` or `\` => Keep `char` as-is.
174
+ end
175
+ res .add char
176
+ i += 1
177
+ end
178
+ return res .to_s
179
+ end
180
+
181
+
123
182
# Encode `self` in JSON.
124
183
#
125
184
# ~~~
126
185
# assert "\t\"http://example.com\"\r\n\0\\".to_json ==
127
- # "\"\\t\\\"http:\\/\\ /example.com\\\"\\r\\n\\u0000\\\\\""
186
+ # "\"\\t\\\"http:/ /example.com\\\"\\r\\n\\u0000\\\\\""
128
187
# ~~~
129
- redef fun to_json do return to_json_by_append
188
+ redef fun to_json do
189
+ var b = new FlatBuffer .with_capacity (bytelen )
190
+ append_json (b )
191
+ return b .to_s
192
+ end
130
193
131
194
# Parse `self` as JSON.
132
195
#
@@ -173,6 +236,16 @@ redef class Text
173
236
end
174
237
end
175
238
239
+ redef class FlatText
240
+ redef fun json_need_escape do
241
+ var its = items
242
+ for i in [first_byte .. last_byte ] do
243
+ if its [i ] == 0x5Cu8 then return true
244
+ end
245
+ return false
246
+ end
247
+ end
248
+
176
249
redef class Buffer
177
250
178
251
# Append the JSON representation of `jsonable` to `self`.
424
497
425
498
redef class Nstring
426
499
# The represented string.
427
- private fun to_nit_string : String do
428
- var res = new Buffer
429
- var i = 1
430
- while i < text .length - 1 do
431
- var char = text [i ]
432
- if char == '\\' then
433
- i += 1
434
- char = text [i ]
435
- if char == 'b' then
436
- char = 0x08 .code_point
437
- else if char == 'f' then
438
- char = 0x0C .code_point
439
- else if char == 'n' then
440
- char = '\n'
441
- else if char == 'r' then
442
- char = '\r'
443
- else if char == 't' then
444
- char = '\t'
445
- else if char == 'u' then
446
- var escape = new Buffer
447
- escape .append "\\u "
448
- var code = text .substring (i + 1 , 4 )
449
- escape .append code
450
- var hx = code .to_hex
451
- if hx >= 0xD800 and hx <= 0xDFFF then
452
- var lostr = text .substring (i + 7 , 4 )
453
- if lostr .length < 4 then
454
- escape .clear
455
- escape .append "\\uFFFD "
456
- else
457
- escape .append "\\u "
458
- escape .append lostr
459
- end
460
- i += 6
461
- end
462
- i += 4
463
- char = escape .from_utf16_escape
464
- end
465
- # `"`, `/` or `\` => Keep `char` as-is.
466
- end
467
- res .add char
468
- i += 1
469
- end
470
- return res .to_s
471
- end
500
+ private fun to_nit_string : String do return text .substring (1 , text .length - 2 ).unescape_json .to_s
472
501
end
473
502
474
503
redef class Nvalue_object
0 commit comments