diff --git a/Serializing/Makefile b/Serializing/Makefile new file mode 100644 index 0000000..29d671d --- /dev/null +++ b/Serializing/Makefile @@ -0,0 +1,6 @@ + + +test: test.cpp + g++ test.cpp -o test -std=c++11 + + diff --git a/Serializing/Makefile b/Serializing/Makefile new file mode 100644 index 0000000..29d671d --- /dev/null +++ b/Serializing/Makefile @@ -0,0 +1,6 @@ + + +test: test.cpp + g++ test.cpp -o test -std=c++11 + + diff --git a/Serializing/ideas.txt b/Serializing/ideas.txt new file mode 100644 index 0000000..845d27a --- /dev/null +++ b/Serializing/ideas.txt @@ -0,0 +1,71 @@ + + +Item - A Serializable thing + - has children which need to be Items + +String is an Item +Array is an Item + +class SerializerVisitor +{ +public: + void Enter(const char* name) + { + } + void Exit(const char* name) + { + } + void Visit(int32 var) + { + } + template + void Visit(const char* name, T var) + { + Enter(name); + Visit(var); + Exit(name); + } + template + void Visit(const char* name, T var) + { + Enter(name); + var.Visit(this); + Exit(name); + } +}; + + +struct Person +{ + int32 id; + string name; + Array email; + Array phoneNumbers; + + // This can do both the serializing and de-serializing + // This might be good to have generated, but possibly being more explicit could be better too + template + void Visit(V& v) + { + v.Visit("id",id); + v.Visit("name",name); + v.Visit("email",email); + v.Visit("numbers",phoneNumbers); + } +} + + +If use JSON, then order of members doesn't matter +Also schema can change, have members added, reordered etc, and can still work +JSON doesn't handle member names changing +Pretty similar for XML +JSON and XML have heavy overhead in size and parsing / writing + +EXI seperates the schema and data - avoids much of the overheads + +Protocol Buffers? Looks like code generation + +Pickling - Python specific + + + diff --git a/Serializing/Makefile b/Serializing/Makefile new file mode 100644 index 0000000..29d671d --- /dev/null +++ b/Serializing/Makefile @@ -0,0 +1,6 @@ + + +test: test.cpp + g++ test.cpp -o test -std=c++11 + + diff --git a/Serializing/ideas.txt b/Serializing/ideas.txt new file mode 100644 index 0000000..845d27a --- /dev/null +++ b/Serializing/ideas.txt @@ -0,0 +1,71 @@ + + +Item - A Serializable thing + - has children which need to be Items + +String is an Item +Array is an Item + +class SerializerVisitor +{ +public: + void Enter(const char* name) + { + } + void Exit(const char* name) + { + } + void Visit(int32 var) + { + } + template + void Visit(const char* name, T var) + { + Enter(name); + Visit(var); + Exit(name); + } + template + void Visit(const char* name, T var) + { + Enter(name); + var.Visit(this); + Exit(name); + } +}; + + +struct Person +{ + int32 id; + string name; + Array email; + Array phoneNumbers; + + // This can do both the serializing and de-serializing + // This might be good to have generated, but possibly being more explicit could be better too + template + void Visit(V& v) + { + v.Visit("id",id); + v.Visit("name",name); + v.Visit("email",email); + v.Visit("numbers",phoneNumbers); + } +} + + +If use JSON, then order of members doesn't matter +Also schema can change, have members added, reordered etc, and can still work +JSON doesn't handle member names changing +Pretty similar for XML +JSON and XML have heavy overhead in size and parsing / writing + +EXI seperates the schema and data - avoids much of the overheads + +Protocol Buffers? Looks like code generation + +Pickling - Python specific + + + diff --git a/Serializing/test.cpp b/Serializing/test.cpp new file mode 100644 index 0000000..388fc07 --- /dev/null +++ b/Serializing/test.cpp @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include +#include + + +template +using Array = std::vector; +using String = std::string; +using Integer32 = int32_t; + + +template +void Visit(V& v, Integer32& i) +{ + v.Visit(i); +} + +template +void Visit(V& v, String& str) +{ + v.Visit(str); +} + +template +void Visit(V& v, Array& arr) +{ + v.Visit(arr); +} + +template +void Visit(V& v, const char* name, T& var) +{ + v.Enter(name); + var.Visit(v); + v.Exit(name); +} + + +class XMLSerializerVisitor +{ +public: + void Enter(const char* name) + { + indent(depth); + output += "<"; + output += name; + output += ">\n"; + depth++; + } + + void Exit(const char* name) + { + depth--; + indent(depth); + output += "\n"; + } + + template + void Visit(Array& arr) + { + Integer32 siz = arr.size(); + Visit("length", siz); + for (int i = 0; i < arr.size(); i++) + { + char buf[1024]; + snprintf(buf, 1024, "element[%i]", i); + Visit(buf, arr.at(i)); + } + } + + void Visit(Integer32& var) + { + indent(depth); + output += std::to_string(var); + output += "\n"; + } + + void Visit(String& var) + { + // TODO: limitiation is that the string can not have a new line + indent(depth); + output += var; + output += "\n"; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + ::Visit(*this, var); + Exit(name); + } + + std::string& Output() + { + return output; + } + void reset() + { + output = ""; + depth = 0; + } +private: + int depth = 0; + std::string output; + + void indent(int spaces) + { + for(int i = 0; i < spaces; i++) + { + output += " "; + } + } +}; + + + +class XMLDeserializerVisitor +{ +public: + XMLDeserializerVisitor(std::string data) : input(data) {} + + void Enter(const char* name) + { + String str; + Visit(str); + //printf("enter deserializing for -%s-, got -%s-\n", name, str.c_str()); + } + void Exit(const char* name) + { + String str; + Visit(str); + //printf("exit deserializing for -%s-, got -%s-\n", name, str.c_str()); + } + + template + void Visit(Array& arr) + { + Integer32 siz = 0; + Visit("length", siz); + arr.resize(siz); + //printf("deserializing array of len: %i\n", siz); + for (int i = 0; i < arr.size(); i++) + { + char buf[1024]; + snprintf(buf, 1024, "element[%i]", i); + Visit(buf, arr.at(i)); + } + } + + 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) + { + stripWhiteSpace(); + int newLineOff = input.find("\n", offset); + var = input.substr(offset, newLineOff-offset); + offset = newLineOff; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + ::Visit(*this, var); + Exit(name); + } + +private: + std::string input; + int offset = 0; + void stripWhiteSpace() + { + while (isspace(input.c_str()[offset])) + { + offset++; + } + } +}; + + + + +struct Person +{ + Integer32 id; + String name; + Array email; + Array phoneNumbers; + + // This can do both the serializing and de-serializing + // This might be good to have generated, but possibly being more explicit could be better too + // Also note the members could be private and this will still work + template + void Visit(V& v) + { + v.Visit("id",id); + v.Visit("name",name); + v.Visit("email",email); + v.Visit("numbers",phoneNumbers); + } +}; + + + + + +int main(int argc, char* argv[]) +{ + std::string input; + + { + 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"); + + XMLSerializerVisitor serializer; + Visit(serializer, "personA", a); + printf("%s", serializer.Output().c_str()); + input = serializer.Output(); + } + + { + Person b; + + XMLDeserializerVisitor deserializer(input); + Visit(deserializer, "personB", b); + + { + XMLSerializerVisitor serializer; + Visit(serializer, "personB", b); + printf("%s", serializer.Output().c_str()); + } + } +} + + + +