Skip to content

Commit

Permalink
Don't escape Unicode in JSON output by default, but add convertJsonTo…
Browse files Browse the repository at this point in the history
…ASCII(). Fixes #809.
  • Loading branch information
s-ludwig committed Sep 5, 2014
1 parent 02e755b commit 26e1fba
Showing 1 changed file with 43 additions and 35 deletions.
78 changes: 43 additions & 35 deletions source/vibe/data/json.d
Expand Up @@ -1704,57 +1704,65 @@ void writePrettyJsonString(R)(ref R dst, in Json json, int level = 0)
}


/**
Helper function that escapes all Unicode characters in a JSON string.
*/
string convertJsonToASCII(string json)
{
auto ret = appender!string;
jsonEscape!true(ret, json);
return ret.data;
}


/// private
private void jsonEscape(R)(ref R dst, string s)
private void jsonEscape(bool escape_unicode = false, R)(ref R dst, string s)
{
size_t pos;
for ( pos = 0; pos < s.length; pos++ ){
for (size_t pos = 0; pos < s.length; pos++) {
immutable(char) ch = s[pos];

switch(ch){
switch (ch) {
default:
if (ch < 0x80)
{
dst.put(ch);
}
else {
import std.utf : decode;
char[13] buf;
int len;
dchar codepoint = decode(s, pos);
import std.c.stdio : sprintf;
/* codepoint is in BMP */
if(codepoint < 0x10000)
{
sprintf(&buf[0], "\\u%04X", codepoint);
len = 6;
}
/* not in BMP -> construct a UTF-16 surrogate pair */
else
{
int first, last;
static if (escape_unicode) {
if (ch < 0x80) dst.put(ch);
else {
import std.utf : decode;
char[13] buf;
int len;
dchar codepoint = decode(s, pos);
import std.c.stdio : sprintf;
/* codepoint is in BMP */
if(codepoint < 0x10000)
{
sprintf(&buf[0], "\\u%04X", codepoint);
len = 6;
}
/* not in BMP -> construct a UTF-16 surrogate pair */
else
{
int first, last;

codepoint -= 0x10000;
first = 0xD800 | ((codepoint & 0xffc00) >> 10);
last = 0xDC00 | (codepoint & 0x003ff);
codepoint -= 0x10000;
first = 0xD800 | ((codepoint & 0xffc00) >> 10);
last = 0xDC00 | (codepoint & 0x003ff);

sprintf(&buf[0], "\\u%04X\\u%04X", first, last);
len = 12;
}
sprintf(&buf[0], "\\u%04X\\u%04X", first, last);
len = 12;
}

pos -= 1;
foreach (i; 0 .. len)
dst.put(buf[i]);
pos -= 1;
foreach (i; 0 .. len)
dst.put(buf[i]);

}
}
} else dst.put(ch);
break;
case '\\': dst.put("\\\\"); break;
case '\r': dst.put("\\r"); break;
case '\n': dst.put("\\n"); break;
case '\t': dst.put("\\t"); break;
case '\"': dst.put("\\\""); break;
}

}
}

Expand Down

0 comments on commit 26e1fba

Please sign in to comment.