Jelajahi Sumber

chore: fix project imports

fix: add to/from json for std::optional

fix: separate stream functions from parser impls for import handling

fix: import strconv for pointers
Sam Jaffe 2 tahun lalu
induk
melakukan
3aeeabe4fc

+ 4 - 0
include/serializer/jsonizer.h

@@ -38,6 +38,10 @@ public:
   void from_json(std::shared_ptr<T const> & ptr,
                  Json::Value const & json) const;
 
+  template <typename T> Json::Value to_json(std::optional<T> const & opt) const;
+  template <typename T>
+  void from_json(std::optional<T> & opt, Json::Value const & json) const;
+
   /**
    * @brief Construct an object of type 'T' from a datastream
    * @param T the output type to be deserialized

+ 10 - 31
include/serializer/jsonizer.tpp

@@ -7,8 +7,6 @@
 
 #pragma once
 
-#include <fstream>
-#include <iostream>
 #include <stdexcept>
 
 #include <expect/expect.hpp>
@@ -17,6 +15,7 @@
 #include <string_utils/cast.h>
 
 #include <serializer/jsonizer.h>
+#include <serializer/jsonizer_ios.tpp>
 #include <serializer/shared_cache.h>
 #include <serializer/strconv.h>
 #include <serializer/traits.h>
@@ -41,6 +40,10 @@ Json::Value Jsonizer::to_json(T & value, std::index_sequence<Is...>) const {
   return json;
 }
 
+template <typename T> Json::Value Jsonizer::to_json(std::optional<T> const &opt) const {
+  return opt.has_value() ? to_json(*opt) : Json::Value();
+}
+
 template <typename T> Json::Value Jsonizer::to_json(T const & value) const {
   if constexpr (detail::has_serial_type_v<T>) {
     return to_json(static_cast<typename T::serial_type>(value));
@@ -91,6 +94,11 @@ void Jsonizer::from_json(T & value, Json::Value const & json,
        0)...};
 }
 
+template <typename T>
+void Jsonizer::from_json(std::optional<T> &opt, Json::Value const & json) const {
+  opt = json.isNull() ? std::nullopt : std::optional{from_json<T>(json)};
+}
+
 template <typename T>
 void Jsonizer::from_json(T & value, Json::Value const & json) const {
   if (json.isNull()) return;
@@ -167,33 +175,4 @@ void Jsonizer::from_json(std::shared_ptr<T const> & ptr,
     ptr = p_cache->store(local.name, local);
   }
 }
-
-template <typename T> T Jsonizer::from_json(Json::Value const & json) const {
-  std::decay_t<T> tmp;
-  from_json(tmp, json);
-  return tmp;
-}
-
-template <typename T> T Jsonizer::from_stream(std::istream & in) const {
-  Json::Value root;
-  in >> root;
-  return from_json<T>(root);
-}
-
-template <typename T> T Jsonizer::from_string(std::string const & in) const {
-  std::stringstream ss;
-  ss << in;
-  return from_stream<T>(ss);
-}
-
-template <typename T>
-void Jsonizer::to_stream(T const & value, std::ostream & out) const {
-  Json::Value root = to_json(value);
-  out << root;
-}
-
-template <typename T> T Jsonizer::from_file(std::string const & file) const {
-  std::ifstream in(file);
-  return from_stream<T>(in);
-}
 }

+ 44 - 0
include/serializer/jsonizer_ios.tpp

@@ -0,0 +1,44 @@
+//
+//  jsonizer_ios.tpp
+//  serializer
+//
+//  Created by Sam Jaffe on 3/18/23.
+//
+
+#include <fstream>
+#include <sstream>
+
+#include <json/json.h>
+
+#include <serializer/jsonizer.h>
+
+namespace serializer {
+template <typename T> T Jsonizer::from_json(Json::Value const & json) const {
+  std::decay_t<T> tmp;
+  from_json(tmp, json);
+  return tmp;
+}
+
+template <typename T> T Jsonizer::from_stream(std::istream & in) const {
+  Json::Value root;
+  in >> root;
+  return from_json<T>(root);
+}
+
+template <typename T> T Jsonizer::from_string(std::string const & in) const {
+  std::stringstream ss;
+  ss << in;
+  return from_stream<T>(ss);
+}
+
+template <typename T>
+void Jsonizer::to_stream(T const & value, std::ostream & out) const {
+  Json::Value root = to_json(value);
+  out << root;
+}
+
+template <typename T> T Jsonizer::from_file(std::string const & file) const {
+  std::ifstream in(file);
+  return from_stream<T>(in);
+}
+}

+ 4 - 4
include/serializer/strconv.h

@@ -20,12 +20,12 @@ using ::std::to_string;
 inline std::string to_string(char const * str) { return str; }
 inline std::string to_string(std::string const & str) { return str; }
 inline std::string to_string(std::string_view str) { return std::string(str); }
-template <typename T> std::string to_string(T const * t) {
-  return to_string(*t);
-}
 
 template <typename T> std::string to_string(T const & elem) {
-  if constexpr (std::is_enum_v<T>) {
+  if constexpr (detail::is_dereferencable_v<T>) {
+    using ::serializer::to_string;
+    return elem ? "nil" : to_string(*elem);
+  } else if constexpr (std::is_enum_v<T>) {
     constexpr auto type =
         magic_enum::as_flags<magic_enum::detail::is_flags_v<T>>;
     return std::string(magic_enum::enum_name<type>(elem));

+ 6 - 0
include/serializer/traits.h

@@ -35,6 +35,11 @@ template <typename T>
 struct has_serial_type<T, std::void_t<typename T::serial_type>>
     : std::true_type {};
 
+template <typename, typename = void>
+struct is_dereferencable : std::false_type {};
+template <typename T>
+struct is_dereferencable<T, std::enable_if_t<!std::is_void_v<decltype(*T())>>> : std::true_type {};
+
 template <typename T> constexpr bool is_tuple_v = is_tuple<T>{};
 template <typename T> constexpr bool is_container_v = is_container<T>{};
 template <typename T>
@@ -42,4 +47,5 @@ constexpr bool is_associative_container_v =
     is_container_v<T> && is_associative_container<T>{};
 
 template <typename T> constexpr bool has_serial_type_v = has_serial_type<T>{};
+template <typename T> constexpr bool is_dereferencable_v = is_dereferencable<T>{};
 }

+ 2 - 0
serializer.xcodeproj/project.pbxproj

@@ -128,6 +128,7 @@
 		CD592C2829C3DC76009AC14E /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
 		CD592C3729C3DC84009AC14E /* string-utils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "string-utils.xcodeproj"; path = "external/string-utils/string-utils.xcodeproj"; sourceTree = "<group>"; };
 		CDD476C629C5468E00BDB829 /* expect.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = expect.xcodeproj; path = external/expect/expect.xcodeproj; sourceTree = "<group>"; };
+		CDE93F8D29C5F8390086A8CA /* jsonizer_ios.tpp */ = {isa = PBXFileReference; lastKnownFileType = text; path = jsonizer_ios.tpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -188,6 +189,7 @@
 				CD592C0B29C2A6C8009AC14E /* forwards.h */,
 				CD592C0729C2A607009AC14E /* jsonizer.h */,
 				CD592C0829C2A610009AC14E /* jsonizer.tpp */,
+				CDE93F8D29C5F8390086A8CA /* jsonizer_ios.tpp */,
 				CD592C0929C2A63A009AC14E /* shared_cache.h */,
 				CD592C0A29C2A64C009AC14E /* strconv.h */,
 				CD592C0C29C2A707009AC14E /* traits.h */,