From ecc3e96da8d66b9c25ab3635b68d176ff9b5456d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 25 Jan 2023 10:37:12 +0530 Subject: [PATCH] Fix JSON serialization of numeric types --- src/calibre/utils/windows/winspeech.cpp | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/calibre/utils/windows/winspeech.cpp b/src/calibre/utils/windows/winspeech.cpp index 7c41293716..40a6190fab 100644 --- a/src/calibre/utils/windows/winspeech.cpp +++ b/src/calibre/utils/windows/winspeech.cpp @@ -183,7 +183,7 @@ private: case DT_NONE: out << "nil"; break; case DT_BOOL: - out << b ? "true" : "false"; break; + out << (b ? "true" : "false"); break; case DT_INT: // this is not really correct since JS has various limits on numeric types, but good enough for us serialize_integer(out, i); break; @@ -226,22 +226,24 @@ public: json_val(winrt::hstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {} json_val(std::wstring const& text) : type(DT_STRING), s(winrt::to_string(text)) {} json_val(std::string_view text) : type(DT_STRING), s(text) {} - json_val(int32_t num) : type(DT_INT), i(num) {} - json_val(int64_t num) : type(DT_INT), i(num) {} json_val(std::vector &&items) : type(DT_LIST), list(items) {} json_val(std::map &&m) : type(DT_OBJECT), object(m) {} json_val(std::initializer_list> const& vals) : type(DT_OBJECT), object(vals) { } - json_val(bool x) : type(DT_BOOL), b(x) {} - json_val(double x) : type(DT_FLOAT), f(x) {} - json_val(HRESULT hr) : type(DT_STRING) { + static json_val from_bool(bool x) { json_val ans; ans.type = DT_BOOL; ans.b = x; return ans; } + static json_val from_double(double x) { json_val ans; ans.type = DT_FLOAT; ans.f = x; return ans; } + static json_val from_integer(int64_t x) { json_val ans; ans.type = DT_INT; ans.i = x; return ans; } + + static json_val from_hresult(HRESULT hr) { + json_val ans; ans.type = DT_STRING; std::array str; str[0] = '0'; str[1] = 'x'; if (auto [ptr, ec] = std::to_chars(str.data()+2, str.data() + str.size(), (uint32_t)hr, 16); ec == std::errc()) { - s = std::string(str.data(), ptr - str.data()); + ans.s = std::string(str.data(), ptr - str.data()); } else { throw std::exception(std::make_error_code(ec).message().c_str()); } + return ans; } json_val(VoiceInformation const& voice) : type(DT_OBJECT) { @@ -298,8 +300,8 @@ public: {"type", json_val(label)}, {"text", json_val(cue.Text())}, {"start_time", json_val(cue.StartTime())}, - {"start_pos_in_text", json_val(cue.StartPositionInInput().Value())}, - {"end_pos_in_text", json_val(cue.EndPositionInInput().Value())}, + {"start_pos_in_text", json_val::from_integer(cue.StartPositionInInput().Value())}, + {"end_pos_in_text", json_val::from_integer(cue.EndPositionInInput().Value())}, }; } @@ -320,8 +322,8 @@ output(id_type cmd_id, std::string_view const &msg_type, json_val const &&msg) { static void output_error(id_type cmd_id, std::string_view const &msg, std::string_view const &error, int64_t line, HRESULT hr=S_OK) { - std::map m = {{"msg", json_val(msg)}, {"error", json_val(error)}, {"file", json_val("winspeech.cpp")}, {"line", json_val(line)}}; - if (hr != S_OK) m["hr"] = json_val(hr); + std::map m = {{"msg", json_val(msg)}, {"error", json_val(error)}, {"file", json_val("winspeech.cpp")}, {"line", json_val::from_integer(line)}}; + if (hr != S_OK) m["hr"] = json_val::from_hresult(hr); output(cmd_id, "error", std::move(m)); } @@ -831,6 +833,7 @@ class Synthesizer { stop_current_activity(); current_cmd_id.store(cmd_id); } + output(cmd_id, "synthesizing", {{"ssml", json_val::from_bool(is_ssml)}}); bool ok = false; try { if (is_ssml) stream = co_await synth.SynthesizeSsmlToStreamAsync(text); @@ -931,7 +934,7 @@ handle_stdin_message(winrt::hstring const &&msg) { auto vol = parse_double(parts[0].data()); sx.volume(vol); } - output(cmd_id, "volume", {{"value", json_val(sx.volume())}}); + output(cmd_id, "volume", {{"value", json_val::from_double(sx.volume())}}); } else throw std::string("Unknown command: ") + winrt::to_string(command); } CATCH_ALL_EXCEPTIONS("Error handling input message", cmd_id);