diff --git a/include/json5/json5_input.hpp b/include/json5/json5_input.hpp index 2ac4a48..ac9178e 100644 --- a/include/json5/json5_input.hpp +++ b/include/json5/json5_input.hpp @@ -187,7 +187,7 @@ inline error parser::parse_value( value &result ) else if ( lit == token_type::literal_false ) result = value( false ); else if ( lit == token_type::literal_null ) - result = value(); + result = value(nullptr); else return make_error( error::invalid_literal ); } diff --git a/include/json5/json5_reflect.hpp b/include/json5/json5_reflect.hpp index d11caab..6fece12 100644 --- a/include/json5/json5_reflect.hpp +++ b/include/json5/json5_reflect.hpp @@ -37,6 +37,12 @@ template error from_file( std::string_view fileName, T &out ); namespace detail { +template struct is_optional : public std::false_type { }; + +template struct is_optional> : public std::true_type { }; + +template constexpr static bool is_optional_v = is_optional::value; + // Pre-declare so compiler knows it exists before it is attempted to be used template error read(const json5::value& in, T& out); @@ -149,6 +155,26 @@ inline json5::value write_enum( writer &w, T in ) return json5::value(); } +//--------------------------------------------------------------------------------------------------------------------- +template +inline void write_tuple_value(writer& w, std::string_view name, const Type& in) +{ + if constexpr (is_optional_v) + { + if (in) + write_tuple_value(w, name, *in); + } + else if constexpr (std::is_enum_v) + { + if constexpr ( enum_table() ) + w[name] = write_enum( w, in ); + else + w[name] = write( w, std::underlying_type_t( in ) ); + } + else + w[name] = write( w, in ); +} + //--------------------------------------------------------------------------------------------------------------------- template inline void write_tuple( writer &w, const char *names, const std::tuple &t ) @@ -158,15 +184,7 @@ inline void write_tuple( writer &w, const char *names, const std::tuple ) - { - if constexpr ( enum_table() ) - w[name] = write_enum( w, in ); - else - w[name] = write( w, std::underlying_type_t( in ) ); - } - else - w[name] = write( w, in ); + write_tuple_value(w, name, in); } if constexpr ( Index + 1 != sizeof...( Types ) ) @@ -349,6 +367,48 @@ inline error read_enum( const json5::value &in, T &out ) return { error::invalid_enum }; } +//--------------------------------------------------------------------------------------------------------------------- +template +inline error read_tuple_value( const json5::object_view::iterator iter, Type &out ) +{ + if constexpr (is_optional_v) + { + if ((*iter).second.is_null()) + { + out = std::nullopt; + } + else + { + out = typename Type::value_type(); + if (auto err = read_tuple_value(iter, *out)) + return err; + } + } + else if constexpr (std::is_enum_v) + { + if constexpr ( enum_table() ) + { + if ( auto err = read_enum( ( *iter ).second, out ) ) + return err; + } + else + { + std::underlying_type_t temp; + if ( auto err = read( ( *iter ).second, temp ) ) + return err; + + out = Type( temp ); + } + } + else + { + if ( auto err = read( ( *iter ).second, out ) ) + return err; + } + + return { error::none }; +} + //--------------------------------------------------------------------------------------------------------------------- template inline error read_tuple( const json5::object_view &obj, const char *names, std::tuple &t ) @@ -361,27 +421,8 @@ inline error read_tuple( const json5::object_view &obj, const char *names, std:: auto iter = obj.find( name ); if ( iter != obj.end() ) { - if constexpr ( std::is_enum_v ) - { - if constexpr ( enum_table() ) - { - if ( auto err = read_enum( ( *iter ).second, out ) ) - return err; - } - else - { - std::underlying_type_t temp; - if ( auto err = read( ( *iter ).second, temp ) ) - return err; - - out = Type( temp ); - } - } - else - { - if ( auto err = read( ( *iter ).second, out ) ) - return err; - } + if ( auto err = read_tuple_value( iter, out ) ) + return err; } if constexpr ( Index + 1 != sizeof...( Types ) )