diff --git a/src/Store/Json.cpp b/src/Store/Json.cpp index 1eaa001..db405b6 100644 --- a/src/Store/Json.cpp +++ b/src/Store/Json.cpp @@ -2,14 +2,18 @@ namespace ToolFramework { -bool json_encode(std::ostream& output, const std::string& datum) { +bool json_encode(std::ostream& output, const char* datum) { output << '"'; - for (char c : datum) { - if (c == '"' || c == '\\') output << '\\'; - output << c; + while (*datum) { + if (*datum == '"' || *datum == '\\') output << '\\'; + output << *datum; }; output << '"'; return true; -} +}; + +bool json_encode(std::ostream& output, const std::string& datum) { + return json_encode(output, datum.c_str()); +}; } diff --git a/src/Store/Json.h b/src/Store/Json.h index 9118d16..4e71727 100644 --- a/src/Store/Json.h +++ b/src/Store/Json.h @@ -10,6 +10,15 @@ namespace ToolFramework { +template +bool json_encode(std::ostream&, const std::array&); + +template +bool json_encode(std::ostream&, const std::vector&); + +template +bool json_encode(std::ostream&, const std::map&); + template typename std::enable_if::value, bool>::type json_encode(std::ostream& output, T datum) { @@ -17,22 +26,32 @@ json_encode(std::ostream& output, T datum) { return true; } +bool json_encode(std::ostream& output, const char* datum); bool json_encode(std::ostream& output, const std::string& datum); template -bool json_encode(std::ostream& output, const std::vector& data) { +bool json_encode(std::ostream& output, const T* data, size_t size) { output << '['; bool comma = false; - for (const T& datum : data) { + for (size_t i = 0; i < size; ++i) { if (comma) output << ','; - else - comma = true; - json_encode(output, datum); + comma = true; + if (!json_encode(output, data[i])) return false; }; output << ']'; return true; -} +}; + +template +bool json_encode(std::ostream& output, const std::array& array) { + return json_encode(output, array.data(), array.size()); +}; + +template +bool json_encode(std::ostream& output, const std::vector& vector) { + return json_encode(output, vector.data(), vector.size()); +}; template bool json_encode(std::ostream& output, const std::map& data) { @@ -43,9 +62,9 @@ bool json_encode(std::ostream& output, const std::map& data) { output << ','; else comma = true; - json_encode(output, datum.first); + if (!json_encode(output, datum.first)) return false; output << ':'; - json_encode(output, datum.second); + if (!json_encode(output, datum.second)) return false; }; output << '}'; return true; @@ -59,6 +78,54 @@ bool json_encode(std::string& output, T data) { return true; } +namespace json_internal { + + inline bool json_encode_object_slots(std::ostream& output, bool& comma) { + return true; + }; + + template + bool json_encode_object_slots( + std::ostream& output, + bool& comma, + const char* name, + const Slot& slot, + Rest... rest + ) { + if (comma) output << ','; + comma = true; + output << '"' << name << '"' << ':'; + if (!json_encode(output, slot)) return false; + return json_encode_object_slots(output, comma, rest...); + }; + + template + bool json_encode_object_slots( + std::ostream& output, + bool& comma, + const std::string& name, + const Slot& slot, + Rest... rest + ) { + return json_encode_object_slots(output, comma, name.c_str(), slot, rest...); + }; + +}; // json_internal + + +// A helper function to write fixed-size objects +// Example: call `json_encode_object(output, "x", 42, "a", false)` +// to produce `{"x":42,"a":false}` +template +bool json_encode_object(std::ostream& output, Args... args) { + output << '{'; + bool comma = false; + if (!json_internal::json_encode_object_slots(output, comma, args...)) + return false; + output << '}'; + return true; } +}; // ToolFramework + #endif