diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 25be353a..aa8fe698 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -460,17 +460,35 @@ namespace chaiscript::json { val += '\t'; break; case 'u': { - val += "\\u"; + std::string hex_matches; for (size_t i = 1; i <= 4; ++i) { c = str.at(offset + i); if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { - val += c; + hex_matches += c; } else { throw std::runtime_error( std::string("JSON ERROR: String: Expected hex character in unicode escape, found '") + c + "'"); } } offset += 4; + const auto ch = static_cast(std::stoi(hex_matches, nullptr, 16)); + if (ch < 0x80) { + val += static_cast(ch); + } else if (ch < 0x800) { + val += static_cast(0xC0 | (ch >> 6)); + val += static_cast(0x80 | (ch & 0x3F)); + } else if (ch < 0x10000) { + val += static_cast(0xE0 | (ch >> 12)); + val += static_cast(0x80 | ((ch >> 6) & 0x3F)); + val += static_cast(0x80 | (ch & 0x3F)); + } else if (ch < 0x200000) { + val += static_cast(0xF0 | (ch >> 18)); + val += static_cast(0x80 | ((ch >> 12) & 0x3F)); + val += static_cast(0x80 | ((ch >> 6) & 0x3F)); + val += static_cast(0x80 | (ch & 0x3F)); + } else { + throw std::runtime_error(std::string("JSON ERROR: String: Invalid 32 bit universal character")); + } } break; default: val += '\\';