diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 975df388..a8a7e87f 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -19,4 +19,4 @@ elseif(ENABLE_SQLITE3) target_link_libraries(${PROJECT_NAME} sqlite3) endif() -install(TARGETS ${PROJECT_NAME} DESTINATION ormpp) \ No newline at end of file +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) \ No newline at end of file diff --git a/iguana/detail/utf.hpp b/iguana/detail/utf.hpp index a6fa7012..e0dae985 100644 --- a/iguana/detail/utf.hpp +++ b/iguana/detail/utf.hpp @@ -3,6 +3,8 @@ #include #include +#include "iguana/define.h" + namespace iguana { // https://github.com/Tencent/rapidjson/blob/master/include/rapidjson/reader.h template @@ -48,4 +50,101 @@ inline void encode_utf8(OutputStream &os, unsigned codepoint) { os.push_back(static_cast(0x80 | (codepoint & 0x3F))); } } + +// https://github.com/Tencent/rapidjson/blob/master/include/rapidjson/encodings.h +static inline unsigned char GetRange(unsigned char c) { + static const unsigned char type[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 10, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, + 11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, + }; + return type[c]; +} + +// https://github.com/Tencent/rapidjson/blob/master/include/rapidjson/encodings.h +template +inline bool decode_utf8(It &&it, unsigned &codepoint) { + auto c = *(it++); + bool result = true; + auto copy = [&]() IGUANA__INLINE_LAMBDA { + c = *(it++); + codepoint = (codepoint << 6) | (static_cast(c) & 0x3Fu); + }; + auto trans = [&](unsigned mask) IGUANA__INLINE_LAMBDA { + result &= ((GetRange(static_cast(c)) & mask) != 0); + }; + auto tail = [&]() IGUANA__INLINE_LAMBDA { + copy(); + trans(0x70); + }; + if (!(c & 0x80)) { + codepoint = static_cast(c); + return true; + } + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + codepoint = 0; + } + else { + codepoint = (0xFFu >> type) & static_cast(c); + } + switch (type) { + case 2: + tail(); + return result; + case 3: + tail(); + tail(); + return result; + case 4: + copy(); + trans(0x50); + tail(); + return result; + case 5: + copy(); + trans(0x10); + tail(); + tail(); + return result; + case 6: + tail(); + tail(); + tail(); + return result; + case 10: + copy(); + trans(0x20); + tail(); + return result; + case 11: + copy(); + trans(0x60); + tail(); + tail(); + return result; + default: + return false; + } +} + } // namespace iguana diff --git a/iguana/enum_reflection.hpp b/iguana/enum_reflection.hpp index 5b96c52a..9b871f8c 100644 --- a/iguana/enum_reflection.hpp +++ b/iguana/enum_reflection.hpp @@ -35,11 +35,14 @@ inline constexpr std::string_view type_string() { constexpr std::string_view str = get_raw_name(); constexpr auto next1 = str.rfind(sample[pos + 3]); #if defined(_MSC_VER) - constexpr auto s1 = str.substr(pos + 6, next1 - pos - 6); + constexpr std::size_t npos = str.find_first_of(" ", pos); + if (npos != std::string_view::npos) + return str.substr(npos + 1, next1 - npos - 1); + else + return str.substr(pos, next1 - pos); #else - constexpr auto s1 = str.substr(pos, next1 - pos); + return str.substr(pos, next1 - pos); #endif - return s1; } template diff --git a/iguana/json_reader.hpp b/iguana/json_reader.hpp index dfac6e09..6feef512 100644 --- a/iguana/json_reader.hpp +++ b/iguana/json_reader.hpp @@ -635,10 +635,11 @@ IGUANA_INLINE void from_json(T &value, const Byte *data, size_t size, } template -void parse(jvalue &result, It &&it, It &&end); +void parse(jvalue &result, It &&it, It &&end, bool parse_as_double = false); template -inline void parse(jarray &result, It &&it, It &&end) { +inline void parse(jarray &result, It &&it, It &&end, + bool parse_as_double = false) { skip_ws(it, end); match<'['>(it, end); if (*it == ']') @@ -652,7 +653,7 @@ inline void parse(jarray &result, It &&it, It &&end) { } result.emplace_back(); - parse(result.back(), it, end); + parse(result.back(), it, end, parse_as_double); if (*it == ']') IGUANA_UNLIKELY { @@ -666,7 +667,8 @@ inline void parse(jarray &result, It &&it, It &&end) { } template -inline void parse(jobject &result, It &&it, It &&end) { +inline void parse(jobject &result, It &&it, It &&end, + bool parse_as_double = false) { skip_ws(it, end); match<'{'>(it, end); if (*it == '}') @@ -689,7 +691,7 @@ inline void parse(jobject &result, It &&it, It &&end) { match<':'>(it, end); - parse(emplaced.first->second, it, end); + parse(emplaced.first->second, it, end, parse_as_double); if (*it == '}') IGUANA_UNLIKELY { @@ -702,7 +704,7 @@ inline void parse(jobject &result, It &&it, It &&end) { } template -inline void parse(jvalue &result, It &&it, It &&end) { +inline void parse(jvalue &result, It &&it, It &&end, bool parse_as_double) { skip_ws(it, end); switch (*it) { case 'n': @@ -728,7 +730,7 @@ inline void parse(jvalue &result, It &&it, It &&end) { case '-': { double d{}; detail::parse_item(d, it, end); - if (static_cast(d) == d) + if (!parse_as_double && (static_cast(d) == d)) result.emplace(d); else result.emplace(d); @@ -746,11 +748,11 @@ inline void parse(jvalue &result, It &&it, It &&end) { break; case '[': result.template emplace(); - parse(std::get(result), it, end); + parse(std::get(result), it, end, parse_as_double); break; case '{': { result.template emplace(); - parse(std::get(result), it, end); + parse(std::get(result), it, end, parse_as_double); break; } default: @@ -760,11 +762,13 @@ inline void parse(jvalue &result, It &&it, It &&end) { skip_ws(it, end); } -// when Is_view is true, parse str as string_view +// set Is_view == true, parse str as std::string_view +// set parse_as_double == true, parse the number as double in any case template -inline void parse(jvalue &result, It &&it, It &&end, std::error_code &ec) { +inline void parse(jvalue &result, It &&it, It &&end, std::error_code &ec, + bool parse_as_double = false) { try { - parse(result, it, end); + parse(result, it, end, parse_as_double); ec = {}; } catch (const std::runtime_error &e) { result.template emplace(); @@ -774,15 +778,16 @@ inline void parse(jvalue &result, It &&it, It &&end, std::error_code &ec) { template , int> = 0> -inline void parse(T &result, const View &view) { - parse(result, std::begin(view), std::end(view)); +inline void parse(T &result, const View &view, bool parse_as_double = false) { + parse(result, std::begin(view), std::end(view), parse_as_double); } template , int> = 0> -inline void parse(T &result, const View &view, std::error_code &ec) noexcept { +inline void parse(T &result, const View &view, std::error_code &ec, + bool parse_as_double = false) noexcept { try { - parse(result, view); + parse(result, view, parse_as_double); ec = {}; } catch (std::runtime_error &e) { ec = iguana::make_error_code(e.what()); diff --git a/iguana/json_writer.hpp b/iguana/json_writer.hpp index 3d77ff63..2df2bfe8 100644 --- a/iguana/json_writer.hpp +++ b/iguana/json_writer.hpp @@ -8,33 +8,35 @@ namespace iguana { -template , int> = 0> IGUANA_INLINE void to_json(T &&t, Stream &s); -template +template IGUANA_INLINE void render_json_value(Stream &ss, std::optional &val); -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, const T &t); -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, const T &v); -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, const T &v); -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, const T &o); -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_json_value(Stream &s, T &&t); -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_json_value(Stream &s, T &&t); template @@ -42,7 +44,6 @@ IGUANA_INLINE void join(Stream &ss, InputIt first, InputIt last, const T &delim, const F &f) { if (first == last) return; - f(*first++); while (first != last) { ss.push_back(delim); @@ -50,75 +51,85 @@ IGUANA_INLINE void join(Stream &ss, InputIt first, InputIt last, const T &delim, } } -template +template IGUANA_INLINE void render_json_value(Stream &ss, std::nullptr_t) { ss.append("null"); } -template +template IGUANA_INLINE void render_json_value(Stream &ss, bool b) { ss.append(b ? "true" : "false"); }; -template +template IGUANA_INLINE void render_json_value(Stream &ss, char value) { ss.append("\""); ss.push_back(value); ss.append("\""); } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, T value) { char temp[65]; auto p = detail::to_chars(temp, value); ss.append(temp, p - temp); } -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, T v) { ss.append(v.value().data(), v.value().size()); } -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, T &&t) { ss.push_back('"'); - ss.append(t.data(), t.size()); + if constexpr (Is_writing_escape) { + write_string_with_escape(t.data(), t.size(), ss); + } + else { + ss.append(t.data(), t.size()); + } ss.push_back('"'); } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_key(Stream &ss, T &t) { ss.push_back('"'); - render_json_value(ss, t); + render_json_value(ss, t); ss.push_back('"'); } -template , int> = 0> IGUANA_INLINE void render_key(Stream &ss, T &&t) { - render_json_value(ss, std::forward(t)); + render_json_value(ss, std::forward(t)); } -template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, T &&t) { to_json(std::forward(t), ss); } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_json_value(Stream &ss, T val) { static constexpr auto enum_to_str = get_enum_map>(); if constexpr (bool_v) { - render_json_value(ss, static_cast>(val)); + render_json_value( + ss, static_cast>(val)); } else { auto it = enum_to_str.find(val); if (it != enum_to_str.end()) IGUANA_LIKELY { auto str = it->second; - render_json_value(ss, std::string_view(str.data(), str.size())); + render_json_value( + ss, std::string_view(str.data(), str.size())); } else { throw std::runtime_error( @@ -128,27 +139,28 @@ IGUANA_INLINE void render_json_value(Stream &ss, T val) { } } -template +template IGUANA_INLINE void render_json_value(Stream &ss, std::optional &val) { if (!val) { ss.append("null"); } else { - render_json_value(ss, *val); + render_json_value(ss, *val); } } -template +template IGUANA_INLINE void render_array(Stream &ss, const T &v) { ss.push_back('['); join(ss, std::begin(v), std::end(v), ',', [&ss](const auto &jsv) IGUANA__INLINE_LAMBDA { - render_json_value(ss, jsv); + render_json_value(ss, jsv); }); ss.push_back(']'); } -template , int>> +template , int>> IGUANA_INLINE void render_json_value(Stream &ss, const T &t) { if constexpr (std::is_same_v()[0])>>) { @@ -166,30 +178,30 @@ IGUANA_INLINE void render_json_value(Stream &ss, const T &t) { ss.push_back('"'); } else { - render_array(ss, t); + render_array(ss, t); } } -template , int>> IGUANA_INLINE void render_json_value(Stream &ss, const T &o) { ss.push_back('{'); join(ss, o.cbegin(), o.cend(), ',', [&ss](const auto &jsv) IGUANA__INLINE_LAMBDA { - render_key(ss, jsv.first); + render_key(ss, jsv.first); ss.push_back(':'); - render_json_value(ss, jsv.second); + render_json_value(ss, jsv.second); }); ss.push_back('}'); } -template , int>> IGUANA_INLINE void render_json_value(Stream &ss, const T &v) { ss.push_back('['); join(ss, v.cbegin(), v.cend(), ',', [&ss](const auto &jsv) IGUANA__INLINE_LAMBDA { - render_json_value(ss, jsv); + render_json_value(ss, jsv); }); ss.push_back(']'); } @@ -203,24 +215,26 @@ constexpr auto write_json_key = [](auto &s, auto i, s.push_back('"'); }; -template , int>> +template , int>> IGUANA_INLINE void render_json_value(Stream &ss, const T &v) { if (v) { - render_json_value(ss, *v); + render_json_value(ss, *v); } else { ss.append("null"); } } -template , int>> +template , int>> IGUANA_INLINE void render_json_value(Stream &s, T &&t) { using U = typename std::decay_t; s.push_back('['); constexpr size_t size = std::tuple_size_v; for_each(std::forward(t), [&s, size](auto &v, auto i) IGUANA__INLINE_LAMBDA { - render_json_value(s, v); + render_json_value(s, v); if (i != size - 1) IGUANA_LIKELY { s.push_back(','); } @@ -228,16 +242,18 @@ IGUANA_INLINE void render_json_value(Stream &s, T &&t) { s.push_back(']'); } -template , int>> +template , int>> IGUANA_INLINE void render_json_value(Stream &s, T &&t) { std::visit( [&s](auto value) { - render_json_value(s, value); + render_json_value(s, value); }, t); } -template , int>> +template , int>> IGUANA_INLINE void to_json(T &&t, Stream &s) { s.push_back('{'); for_each(std::forward(t), @@ -249,17 +265,17 @@ IGUANA_INLINE void to_json(T &&t, Stream &s) { write_json_key(s, i, t); s.push_back(':'); - render_json_value(s, t.*v); + render_json_value(s, t.*v); if (Idx < Count - 1) IGUANA_LIKELY { s.push_back(','); } }); s.push_back('}'); } -template , int> = 0> IGUANA_INLINE void to_json(T &&t, Stream &s) { - render_json_value(s, t); + render_json_value(s, t); } } // namespace iguana diff --git a/iguana/reflection.hpp b/iguana/reflection.hpp index a32f3e1a..41e15423 100644 --- a/iguana/reflection.hpp +++ b/iguana/reflection.hpp @@ -17,7 +17,6 @@ #include #include -#include "detail/itoa.hpp" #include "detail/string_stream.hpp" #include "detail/traits.hpp" #include "frozen/string.h" diff --git a/iguana/util.hpp b/iguana/util.hpp index b5ec2c3e..3d2605cd 100644 --- a/iguana/util.hpp +++ b/iguana/util.hpp @@ -13,6 +13,7 @@ #include "define.h" #include "detail/charconv.h" +#include "detail/utf.hpp" #include "enum_reflection.hpp" #include "error_code.h" #include "reflection.hpp" @@ -71,7 +72,7 @@ constexpr inline bool map_container_v = is_map_container>::value; template -constexpr inline bool c_array_v = std::is_array_v> && +constexpr inline bool c_array_v = std::is_array_v>&& std::extent_v> > 0; template @@ -175,7 +176,7 @@ template using underline_type_t = typename underline_type>::type; template -IGUANA_INLINE void match(It &&it, It &&end) { +IGUANA_INLINE void match(It&& it, It&& end) { const auto n = static_cast(std::distance(it, end)); if (n < sizeof...(C)) IGUANA_UNLIKELY { @@ -203,4 +204,84 @@ inline constexpr auto has_qoute = [](uint64_t chunk) IGUANA__INLINE_LAMBDA { 0b0010001000100010001000100010001000100010001000100010001000100010); }; +// https://github.com/Tencent/rapidjson/blob/master/include/rapidjson/writer.h +template +inline void write_string_with_escape(const Ch* it, SizeType length, + Stream& ss) { + static const char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + static const char escape[256] = { +#define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + // 0 1 2 3 4 5 6 7 8 9 A B C D E + // F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', + 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', + 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, '\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + auto end = it; + std::advance(end, length); + while (it < end) { + if (static_cast(*it) >= 0x80) + IGUANA_UNLIKELY { + unsigned codepoint = 0; + if (!decode_utf8(it, codepoint)) + IGUANA_UNLIKELY { + throw std::runtime_error("illegal unicode character"); + } + ss.push_back('\\'); + ss.push_back('u'); + if (codepoint <= 0xD7FF || + (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + ss.push_back(hexDigits[(codepoint >> 12) & 15]); + ss.push_back(hexDigits[(codepoint >> 8) & 15]); + ss.push_back(hexDigits[(codepoint >> 4) & 15]); + ss.push_back(hexDigits[(codepoint)&15]); + } + else { + if (codepoint < 0x010000 || codepoint > 0x10FFFF) + IGUANA_UNLIKELY { throw std::runtime_error("illegal codepoint"); } + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + ss.push_back(hexDigits[(lead >> 12) & 15]); + ss.push_back(hexDigits[(lead >> 8) & 15]); + ss.push_back(hexDigits[(lead >> 4) & 15]); + ss.push_back(hexDigits[(lead)&15]); + ss.push_back('\\'); + ss.push_back('u'); + ss.push_back(hexDigits[(trail >> 12) & 15]); + ss.push_back(hexDigits[(trail >> 8) & 15]); + ss.push_back(hexDigits[(trail >> 4) & 15]); + ss.push_back(hexDigits[(trail)&15]); + } + } + else if (escape[static_cast(*it)]) + IGUANA_UNLIKELY { + ss.push_back('\\'); + ss.push_back(escape[static_cast(*it)]); + + if (escape[static_cast(*it)] == 'u') { + // escape other control characters + ss.push_back('0'); + ss.push_back('0'); + ss.push_back(hexDigits[static_cast(*it) >> 4]); + ss.push_back(hexDigits[static_cast(*it) & 0xF]); + } + ++it; + } + else { + ss.push_back(*(it++)); + } + } +} + } // namespace iguana diff --git a/iguana/yaml_writer.hpp b/iguana/yaml_writer.hpp index b6228b99..a0794f2c 100644 --- a/iguana/yaml_writer.hpp +++ b/iguana/yaml_writer.hpp @@ -5,28 +5,34 @@ namespace iguana { -template , int> = 0> IGUANA_INLINE void to_yaml(T &&t, Stream &s, size_t min_spaces = 0); -template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, T &&t, size_t min_spaces) { ss.push_back('\n'); - to_yaml(std::forward(t), ss, min_spaces); + to_yaml(std::forward(t), ss, min_spaces); } -// TODO: support more string style, support escape -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, T &&t, size_t min_spaces) { - ss.append(t.data(), t.size()); + if constexpr (Is_writing_escape) { + ss.push_back('"'); + write_string_with_escape(t.data(), t.size(), ss); + ss.push_back('"'); + } + else { + ss.append(t.data(), t.size()); + } if constexpr (appendLf) ss.push_back('\n'); } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { char temp[65]; auto p = detail::to_chars(temp, value); @@ -35,7 +41,7 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { ss.push_back('\n'); } -template +template IGUANA_INLINE void render_yaml_value(Stream &ss, char value, size_t min_spaces) { ss.push_back(value); @@ -43,7 +49,7 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, char value, ss.push_back('\n'); } -template +template IGUANA_INLINE void render_yaml_value(Stream &ss, bool value, size_t min_spaces) { ss.append(value ? "true" : "false"); @@ -51,21 +57,21 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, bool value, ss.push_back('\n'); } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { static constexpr auto enum_to_str = get_enum_map>(); if constexpr (bool_v) { - render_yaml_value(ss, static_cast>(value), - min_spaces); + render_yaml_value( + ss, static_cast>(value), min_spaces); } else { auto it = enum_to_str.find(value); if (it != enum_to_str.end()) IGUANA_LIKELY { auto str = it->second; - render_yaml_value(ss, std::string_view(str.data(), str.size()), - min_spaces); + render_yaml_value( + ss, std::string_view(str.data(), str.size()), min_spaces); } else { throw std::runtime_error( @@ -75,16 +81,17 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { } } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val, size_t min_spaces); -template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val, size_t min_spaces); -template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &t, size_t min_spaces) { @@ -92,35 +99,37 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, const T &t, for (const auto &v : t) { ss.append(min_spaces, ' '); ss.append("- "); - render_yaml_value(ss, v, min_spaces + 1); + render_yaml_value(ss, v, min_spaces + 1); } } -template , int> = 0> +template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, T &&t, size_t min_spaces) { ss.push_back('\n'); for_each(std::forward(t), [&ss, min_spaces](auto &v, auto i) IGUANA__INLINE_LAMBDA { ss.append(min_spaces, ' '); ss.append("- "); - render_yaml_value(ss, v, min_spaces + 1); + render_yaml_value(ss, v, min_spaces + 1); }); } -template , int> = 0> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &t, size_t min_spaces) { ss.push_back('\n'); for (const auto &[k, v] : t) { ss.append(min_spaces, ' '); - render_yaml_value(ss, k, 0); // key must be plaint type + render_yaml_value(ss, k, 0); // key must be plaint type ss.append(": "); - render_yaml_value(ss, v, min_spaces + 1); + render_yaml_value(ss, v, min_spaces + 1); } } -template , int>> +template , int>> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val, size_t min_spaces) { if (!val) { @@ -128,18 +137,19 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val, ss.push_back('\n'); } else { - render_yaml_value(ss, *val, min_spaces); + render_yaml_value(ss, *val, min_spaces); } } -template , int>> +template , int>> IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val, size_t min_spaces) { if (!val) { ss.push_back('\n'); } else { - render_yaml_value(ss, *val, min_spaces); + render_yaml_value(ss, *val, min_spaces); } } @@ -149,7 +159,8 @@ constexpr auto write_yaml_key = [](auto &s, auto i, s.append(name.data(), name.size()); }; -template , int>> +template , int>> IGUANA_INLINE void to_yaml(T &&t, Stream &s, size_t min_spaces) { for_each(std::forward(t), [&t, &s, min_spaces](const auto &v, auto i) IGUANA__INLINE_LAMBDA { @@ -161,21 +172,21 @@ IGUANA_INLINE void to_yaml(T &&t, Stream &s, size_t min_spaces) { write_yaml_key(s, i, t); s.append(": "); if constexpr (!is_reflection>::value) { - render_yaml_value(s, t.*v, min_spaces + 1); + render_yaml_value(s, t.*v, min_spaces + 1); } else { s.push_back('\n'); - to_yaml(t.*v, s, min_spaces + 1); + to_yaml(t.*v, s, min_spaces + 1); } }); } -template , int> = 0> IGUANA_INLINE void to_yaml(T &&t, Stream &s) { if constexpr (tuple_v || map_container_v || sequence_container_v || optional_v || smart_ptr_v) - render_yaml_value(s, std::forward(t), 0); + render_yaml_value(s, std::forward(t), 0); else static_assert(!sizeof(T), "don't suppport this type"); }