Browse Source

Adding test for custom converter for primitive type.

Sam Jaffe 8 years ago
parent
commit
3fb14f02f1

+ 5 - 2
json.xcodeproj/project.pbxproj

@@ -78,6 +78,7 @@
 		CD679D781E6126C700F9F843 /* json_tc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_tc.cpp; sourceTree = "<group>"; };
 		CD679D7B1E61E26000F9F843 /* json_binder_value_string.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = json_binder_value_string.t.h; sourceTree = "<group>"; };
 		CD679D7C1E6273DB00F9F843 /* json_binder_value_double.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = json_binder_value_double.t.h; sourceTree = "<group>"; };
+		CD84C4EB1F68908F002014D3 /* json_binder_custom.t.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = json_binder_custom.t.h; sourceTree = "<group>"; tabWidth = 2; };
 		CDB2F7331C5D47F70067C2EC /* libjson.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libjson.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDB2F7411C5D48090067C2EC /* json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = json.cpp; sourceTree = "<group>"; tabWidth = 2; };
 		CDB2F7421C5D48090067C2EC /* json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.h; path = json.hpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -87,7 +88,7 @@
 		CDE6CC2B1EF9E984005E745A /* libjson_s.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjson_s.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDECC7D41E64E6A900BEE842 /* json_binder_collection.t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_binder_collection.t.h; sourceTree = "<group>"; };
 		CDECC7D51E6504C800BEE842 /* json_binder_test_bool.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = json_binder_test_bool.t.h; sourceTree = "<group>"; };
-		CDECC7D61E65073E00BEE842 /* json_binder_object.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = json_binder_object.t.h; sourceTree = "<group>"; };
+		CDECC7D61E65073E00BEE842 /* json_binder_object.t.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = json_binder_object.t.h; sourceTree = "<group>"; tabWidth = 2; };
 		CDF643321C6E9A8B0016A475 /* json_tc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = json_tc; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -191,6 +192,7 @@
 				CDECC7D61E65073E00BEE842 /* json_binder_object.t.h */,
 				CDECC7D41E64E6A900BEE842 /* json_binder_collection.t.h */,
 				CD2B09881E6374F300D6D23A /* json_binder_terminate.t.h */,
+				CD84C4EB1F68908F002014D3 /* json_binder_custom.t.h */,
 				CD679D781E6126C700F9F843 /* json_tc.cpp */,
 			);
 			name = test;
@@ -414,13 +416,14 @@
 				"$(SRCROOT)/json_binder_collection.t.h",
 				"$(SRCROOT)/json_binder_test_bool.t.h",
 				"$(SRCROOT)/json_binder_object.t.h",
+				"$(SRCROOT)/json_binder_custom.t.h",
 			);
 			outputPaths = (
 				"$(SRCDIR)/json_tc.cpp",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "cxxtestgen --error-printer -o json_tc.cpp json_binder_value_int.t.h json_binder_value_string.t.h json_binder_value_double.t.h json_binder_terminate.t.h json_binder_tuple.t.h json_binder_collection.t.h json_binder_test_bool.t.h json_binder_object.t.h";
+			shellScript = "cxxtestgen --error-printer -o json_tc.cpp json_binder_value_int.t.h json_binder_value_string.t.h json_binder_value_double.t.h json_binder_terminate.t.h json_binder_tuple.t.h json_binder_collection.t.h json_binder_test_bool.t.h json_binder_object.t.h json_binder_custom.t.h";
 		};
 /* End PBXShellScriptBuildPhase section */
 

+ 6 - 3
json/json_direct_binder.hpp

@@ -9,14 +9,17 @@
 
 namespace json { namespace binder {
   template <typename T, typename E, typename = void>
-  class direct_binder : public binder_impl<T> {
+  class direct_binder;
+  
+  template <typename T, typename E, typename = void>
+  class forward_binder : public binder_impl<T> {
   public:
-    direct_binder(E T::*p, binder<E> const& i) :
+    forward_binder(E T::*p, binder<E> const& i) :
     ptr(p), impl(i) {
     }
     
     virtual binder_impl<T>* clone() const override {
-      return new direct_binder(*this);
+      return new forward_binder(*this);
     }
     
     virtual void parse(T& val, char const*& data, parser::options opts) const override {

+ 1 - 1
json/json_object_binder.hpp

@@ -18,7 +18,7 @@ namespace json { namespace binder {
     
     template <typename V>
     object_binder& operator()(std::string const&k, V T::*ptr, binder_impl<V> const&v) {
-      return (*this)(k, binder<T>(new direct_binder<T, V>(ptr, binder<V>(v) )));
+      return (*this)(k, binder<T>(new forward_binder<T, V>(ptr, binder<V>(v) )));
     }
 
     object_binder& operator()(std::string const&k, binder<T> const&v) {

+ 71 - 0
json_binder_custom.t.h

@@ -0,0 +1,71 @@
+//
+//  json_binder_custom.t.h
+//  json
+//
+//  Created by Sam Jaffe on 9/12/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+#include "json_binder.hpp"
+
+#include <iomanip>
+
+using namespace json::binder;
+using namespace json::parser;
+
+class precision_binder : public binder_impl<double> {
+public:
+  precision_binder(int d) : digits(d), trunc(std::pow(10, d)) {}
+  virtual ~precision_binder() = default;
+  
+  binder_impl<double> * clone() const override {
+    return new precision_binder{*this};
+  }
+  
+  void parse(double & value, char const * & str, options) const override {
+    std::sscanf(str, "%lf", &value);
+    value = static_cast<long long>(value * trunc) / trunc;
+    json::parse_discard_token(str); // Advance to the boundary
+  }
+  
+  void write(double const & value, std::ostream & out) const override {
+    out << std::fixed << std::setprecision(digits) << value;
+  }
+private:
+  int digits;
+  double trunc;
+};
+
+class json_binder_custom_TestSuite : public CxxTest::TestSuite {
+public:
+  struct TestObject {
+    double A; // four_digits
+    double B; // two_digits
+    double C;
+    bool operator==(TestObject const & other) const {
+      return A == other.A && B == other.B && C == other.C;
+    }
+  };
+  
+  static object_binder<TestObject> GetImpl() {
+    return object_binder<TestObject>()
+    ("A", &TestObject::A, precision_binder(4))
+    ("B", &TestObject::B, precision_binder(2))
+    ("C", &TestObject::C);
+  }
+  
+  static object_binder<TestObject> & Get() {
+    static object_binder<TestObject> val = GetImpl();
+    return val;
+  }
+  
+  void test_() {
+    char data[] = "{\"A\":1.00008, \"B\":1.0, \"C\":1.523211102}";
+    TestObject out{0.0, 0.0, 0.0};
+    TestObject const expected{1.0, 1.0, 1.523211102};
+    TS_ASSERT_THROWS_NOTHING(parse(json::binder::bind(out, Get()), data));
+    TS_ASSERT_EQUALS(out, expected);
+  }
+};