diff --git a/Serializing/Makefile b/Serializing/Makefile index 29d671d..2463975 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ test: test.cpp - g++ test.cpp -o test -std=c++11 + g++ test.cpp -o test -std=c++11 diff --git a/Serializing/Makefile b/Serializing/Makefile index 29d671d..2463975 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ test: test.cpp - g++ test.cpp -o test -std=c++11 + g++ test.cpp -o test -std=c++11 diff --git a/Serializing/test.cpp b/Serializing/test.cpp index 388fc07..e0098f1 100644 --- a/Serializing/test.cpp +++ b/Serializing/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include template @@ -32,17 +33,22 @@ } template -void Visit(V& v, const char* name, T& var) +void Visit(V& v, const char* /*name*/, T& var) { - v.Enter(name); + //v.Enter(name); var.Visit(v); - v.Exit(name); + //v.Exit(name); } class XMLSerializerVisitor { public: + XMLSerializerVisitor() + { + reset(); + } + void Enter(const char* name) { indent(depth); @@ -64,6 +70,7 @@ template void Visit(Array& arr) { +/* Integer32 siz = arr.size(); Visit("length", siz); for (int i = 0; i < arr.size(); i++) @@ -72,6 +79,11 @@ snprintf(buf, 1024, "element[%i]", i); Visit(buf, arr.at(i)); } +*/ + for (auto i : arr) + { + Visit("item", i); + } } void Visit(Integer32& var) @@ -99,12 +111,13 @@ std::string& Output() { + output += "\n"; return output; } void reset() { - output = ""; - depth = 0; + output = "\n"; + depth = 1; } private: int depth = 0; @@ -124,7 +137,12 @@ class XMLDeserializerVisitor { public: - XMLDeserializerVisitor(std::string data) : input(data) {} + XMLDeserializerVisitor(std::string data) : input(data) + { + String str; + Visit(str); + // deserialize the tag + } void Enter(const char* name) { @@ -142,6 +160,7 @@ template void Visit(Array& arr) { +/* Integer32 siz = 0; Visit("length", siz); arr.resize(siz); @@ -152,6 +171,20 @@ snprintf(buf, 1024, "element[%i]", i); Visit(buf, arr.at(i)); } +*/ + while (true) + { + int oldOffset = offset; + String str; + Visit(str); + offset = oldOffset; + if (str != "") + break; + + T item; + Visit("item", item); + arr.push_back(item); + } } void Visit(Integer32& var) @@ -166,7 +199,8 @@ { stripWhiteSpace(); int newLineOff = input.find("\n", offset); - var = input.substr(offset, newLineOff-offset); + if (newLineOff != std::string::npos) + var = input.substr(offset, newLineOff-offset); offset = newLineOff; } @@ -191,6 +225,210 @@ }; +class JsonSerializerVisitor +{ +public: + JsonSerializerVisitor() + { + reset(); + } + + void Enter(const char* name) + { + output += indent(depth) + quoted(name) + " : {\n"; + depth++; + } + + void Exit(const char* name) + { + output += "\n" + indent(--depth) + "}\n"; + } + + template + void Visit(Array& arr) + { + output += "[ "; + for (int i = 0; i < arr.size(); i++) + { + Visit(arr.at(i)); + if ( i != arr.size() - 1 ) + output += " ,"; + output += " "; + } + output += "]"; + } + + void Visit(Integer32& var) + { + output += std::to_string(var); + } + + void Visit(String& var) + { + output += quoted(var.c_str()); + } + + template + void Visit(const char* name, T& var) + { + if (lastDepth == depth) + output += " ,\n"; + lastDepth = depth; + + output += indent(depth) + quoted(name) + " : "; + ::Visit(*this, var); + } + + std::string& Output() + { + output += "}\n"; + return output; + } + void reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + + std::string quoted(const char* name) + { + return std::string("\"" + std::string(name) + "\""); + } + std::string indent(int spaces) + { + return std::string(spaces*2, ' '); + } +}; + + + +class JsonDeserializerVisitor +{ +public: + JsonDeserializerVisitor(std::string data) : input(data) + { + String str; + ParseString(str); // gets the '{' + assert(str == "{"); + } + + void ParseString(String& var) + { + stripWhiteSpace(); + int pos = offset; + while (input.c_str()[pos]) + { + if (isspace(input.c_str()[pos])) + { + var = input.substr(offset, pos-offset); + offset = pos; + return; + } + pos++; + } + } + + void Enter(const char* name) + { + String str; + ParseString(str); // gets the name + //printf("name: -%s-", quoted(name).c_str()); + //printf("str: -%s-", str.c_str()); + assert(str == quoted(name)); + ParseString(str); // gets the ':' + assert(str == ":"); + ParseString(str); // gets the '{' + assert(str == "{"); + //printf("enter deserializing for -%s-, got -%s-\n", name, str.c_str()); + } + void Exit(const char* name) + { + String str; + ParseString(str); // gets the '}' + assert(str == "}"); + //printf("exit deserializing for -%s-, got -%s-\n", name, str.c_str()); + } + + template + void Visit(Array& arr) + { + String str; + ParseString(str); // gets the '[' + assert(str == "["); + while (true) + { + T item; + Visit(item); + arr.push_back(item); + + String str; + ParseString(str); // gets the ',' or ']' or '],' + if (str != ",") + { + //printf("expecting ]"); + //printf("str: -%s-", str.c_str()); + assert(str == "]"); + break; + } + } + } + + void Visit(Integer32& var) + { + const char* ptr = input.c_str(); + char* endPtr; + var = strtol(ptr + offset, &endPtr, 10); + offset = endPtr - ptr; + } + + void Visit(String& var) + { + // TODO + stripWhiteSpace(); + int newLineOff = input.find("\"", offset + 1); + if (newLineOff != std::string::npos) + var = input.substr(offset + 1, newLineOff - offset - 1); + offset = newLineOff + 1; + } + + template + void Visit(const char* name, T& var) + { + String str; + ParseString(str); // gets the name + //printf("name: -%s-", quoted(name).c_str()); + //printf("str: -%s-", str.c_str()); + assert(str == quoted(name)); + ParseString(str); // gets the ':' + assert(str == ":"); + ::Visit(*this, var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + +private: + std::string input; + int offset = 0; + std::string quoted(const char* name) + { + return std::string("\"" + std::string(name) + "\""); + } + void stripWhiteSpace() + { + while (isspace(input.c_str()[offset])) + { + offset++; + } + } +}; + struct Person @@ -206,10 +444,12 @@ template void Visit(V& v) { + v.Enter("person"); v.Visit("id",id); v.Visit("name",name); v.Visit("email",email); v.Visit("numbers",phoneNumbers); + v.Exit("person"); } }; @@ -247,6 +487,34 @@ printf("%s", serializer.Output().c_str()); } } + + + { + Person a; + a.id = 10; + a.name = "blah"; + a.email.push_back("em@ail.com"); + a.email.push_back("other@add.com"); + a.phoneNumbers.push_back("123555"); + + JsonSerializerVisitor serializer; + Visit(serializer, "personA", a); + printf("%s", serializer.Output().c_str()); + input = serializer.Output(); + } + + { + Person b; + + JsonDeserializerVisitor deserializer(input); + Visit(deserializer, "personB", b); + + { + JsonSerializerVisitor serializer; + Visit(serializer, "personB", b); + printf("%s", serializer.Output().c_str()); + } + } }