Improved JSON string parsing

This commit is contained in:
Tobias Taschner
2020-01-19 21:32:11 +01:00
parent 26c82d43d1
commit caf9285609
2 changed files with 34 additions and 33 deletions

View File

@@ -14,74 +14,72 @@ namespace wxJSON
{ {
// Decode a string literal including escape sequences // Decode a string literal including escape sequences
// If the input is not quoted string it will be returned as the input // Returns false if the input string is not a valid JSON string
wxString DecodeString(const wxString& str) bool DecodeString(const wxString& in, wxString* out)
{ {
if (!str.starts_with('"') || !str.ends_with('"')) const wxWCharBuffer buf = in.wc_str();
return str; const wchar_t* ch = buf.data();
// String has to chart with a quote
wxString result; if (*(ch++) != '"')
const wxWCharBuffer buf = str.wc_str(); return false;
out->reserve(buf.length());
const wchar_t* end = buf.data() + buf.length() - 1; const wchar_t* end = buf.data() + buf.length() - 1;
for (const wchar_t* ch = buf.data() + 1; ch < end; ++ch) for (; ch < end; ++ch)
{ {
if (*ch == '\\') if (*ch == '\\')
{ {
switch (*(++ch)) switch (*(++ch))
{ {
case 'b': case 'b':
result.append('\b'); out->append('\b');
break; break;
case 'n': case 'n':
result.append('\n'); out->append('\n');
break; break;
case 'r': case 'r':
result.append('\r'); out->append('\r');
break; break;
case 't': case 't':
result.append('\t'); out->append('\t');
break; break;
case 'v': case 'f':
result.append('\v'); out->append('\f');
break; break;
case '\'': case '/':
result.append('\''); out->append('/');
break; break;
case '"': case '"':
result.append('"'); out->append('"');
break; break;
case '\\': case '\\':
result.append('\\'); out->append('\\');
break; break;
case 'u': case 'u':
#if SIZEOF_WCHAR_T == 2
// In this case, we handle surrogates without doing anything special was wchar_t strings use UTF-17 encoding.
if (wxIsxdigit(ch[1]) && wxIsxdigit(ch[2]) && if (wxIsxdigit(ch[1]) && wxIsxdigit(ch[2]) &&
wxIsxdigit(ch[3]) && wxIsxdigit(ch[4])) wxIsxdigit(ch[3]) && wxIsxdigit(ch[4]))
{ {
wxUChar uchar = wxHexToDec(wxString(&ch[3], 2)) | wchar_t uchar = wxHexToDec(wxString(&ch[3], 2)) |
wxHexToDec(wxString(&ch[1], 2)) >> 8; wxHexToDec(wxString(&ch[1], 2)) >> 8;
result.append(uchar); out->append(uchar);
ch += 4; ch += 4;
} }
#else
#error Implement correct surrogate handling.
#endif
break; break;
case 'x':
if (wxIsxdigit(ch[1]) && wxIsxdigit(ch[2]))
{
wxChar hchar = wxHexToDec(wxString(&ch[1], 2));
result.append(hchar);
ch += 2;
}
break;
default: default:
result.append(*ch); return false;
break; break;
} }
} }
else else
result.append(*ch); out->append(*ch);
} }
return result; // String has to end with a quote
return (*ch) == '"';
} }
} // namespace JSON } // namespace JSON

View File

@@ -811,7 +811,10 @@ bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output)
if (RunScriptSync(wrapJS.GetUnwrappedOutputCode() + ";", &result)) if (RunScriptSync(wrapJS.GetUnwrappedOutputCode() + ";", &result))
{ {
if (output) if (output)
*output = wxJSON::DecodeString(result); // Try to decode JSON string or return original
// result if it's not a valid JSON string
if (!wxJSON::DecodeString(result, output))
*output = result;
result.clear(); result.clear();
} }