diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/Makefile b/Serializing/Makefile index 2463975..dbbb129 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ -test: test.cpp - g++ test.cpp -o test -std=c++11 +test: test.cpp StackTrace.cpp + g++ -g test.cpp StackTrace.cpp -o test -std=c++11 -rdynamic diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/Makefile b/Serializing/Makefile index 2463975..dbbb129 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ -test: test.cpp - g++ test.cpp -o test -std=c++11 +test: test.cpp StackTrace.cpp + g++ -g test.cpp StackTrace.cpp -o test -std=c++11 -rdynamic diff --git a/Serializing/StackTrace.cpp b/Serializing/StackTrace.cpp new file mode 100644 index 0000000..f825b38 --- /dev/null +++ b/Serializing/StackTrace.cpp @@ -0,0 +1,78 @@ +#include "StackTrace.h" +#include +#include + + +#ifdef _WIN32 + +#include "DbgHelp.h" +#include +#pragma comment(lib, "Dbghelp.lib") + +void PrintStackTrace() +{ + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + void* stack[60]; + unsigned short frames = CaptureStackBackTrace(0, 60, stack, NULL); + SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + for(int i = 0; i < frames; i++) + { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + printf("%i: %016I64LX %s - 0x%0X\n", frames - i - 1, stack[i], symbol->Name, symbol->Address); + } + free(symbol); +} + +#else + +#include +#include +#include + +char* SplitStringNext(char* str, char ch) +{ + if (!str) + return 0; + int i = 0; + while (str[i] && str[i] != ch) + i++; + if (!str[i]) + return 0; + str[i] = 0; + return &str[i + 1]; +} + +void PrintStackTrace() +{ +#ifdef USE_PSTACK + if (FILE* f = popen(std::string("pstack " + std::to_string(getpid()) + " | c++filt").c_str(), "r")) + { + char ch; + while (fread(&ch, 1, 1, f) > 0) + std::cout << ch; + pclose(f); + } +#else + void *array[128]; + int size = backtrace(array, 128); + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) + { + // messages[i] looks something like this: "./test(_ZN1DC1Ev+0x18) [0x415974]" + char *progName = messages[i]; + char *funcName = SplitStringNext(progName,'('); + char *offsetStr = SplitStringNext(funcName,'+'); + char *addrStr = SplitStringNext(SplitStringNext(offsetStr, ')'), '['); + char *endStr = SplitStringNext(addrStr,']'); + fprintf(stderr, "[bt]: (%d) %s [%s] %s offset: %s \n", i, progName, addrStr, abi::__cxa_demangle(funcName, 0, 0, 0), offsetStr ); + } + free(messages); +#endif +} + +#endif + + diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/Makefile b/Serializing/Makefile index 2463975..dbbb129 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ -test: test.cpp - g++ test.cpp -o test -std=c++11 +test: test.cpp StackTrace.cpp + g++ -g test.cpp StackTrace.cpp -o test -std=c++11 -rdynamic diff --git a/Serializing/StackTrace.cpp b/Serializing/StackTrace.cpp new file mode 100644 index 0000000..f825b38 --- /dev/null +++ b/Serializing/StackTrace.cpp @@ -0,0 +1,78 @@ +#include "StackTrace.h" +#include +#include + + +#ifdef _WIN32 + +#include "DbgHelp.h" +#include +#pragma comment(lib, "Dbghelp.lib") + +void PrintStackTrace() +{ + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + void* stack[60]; + unsigned short frames = CaptureStackBackTrace(0, 60, stack, NULL); + SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + for(int i = 0; i < frames; i++) + { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + printf("%i: %016I64LX %s - 0x%0X\n", frames - i - 1, stack[i], symbol->Name, symbol->Address); + } + free(symbol); +} + +#else + +#include +#include +#include + +char* SplitStringNext(char* str, char ch) +{ + if (!str) + return 0; + int i = 0; + while (str[i] && str[i] != ch) + i++; + if (!str[i]) + return 0; + str[i] = 0; + return &str[i + 1]; +} + +void PrintStackTrace() +{ +#ifdef USE_PSTACK + if (FILE* f = popen(std::string("pstack " + std::to_string(getpid()) + " | c++filt").c_str(), "r")) + { + char ch; + while (fread(&ch, 1, 1, f) > 0) + std::cout << ch; + pclose(f); + } +#else + void *array[128]; + int size = backtrace(array, 128); + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) + { + // messages[i] looks something like this: "./test(_ZN1DC1Ev+0x18) [0x415974]" + char *progName = messages[i]; + char *funcName = SplitStringNext(progName,'('); + char *offsetStr = SplitStringNext(funcName,'+'); + char *addrStr = SplitStringNext(SplitStringNext(offsetStr, ')'), '['); + char *endStr = SplitStringNext(addrStr,']'); + fprintf(stderr, "[bt]: (%d) %s [%s] %s offset: %s \n", i, progName, addrStr, abi::__cxa_demangle(funcName, 0, 0, 0), offsetStr ); + } + free(messages); +#endif +} + +#endif + + diff --git a/Serializing/StackTrace.h b/Serializing/StackTrace.h new file mode 100644 index 0000000..8153460 --- /dev/null +++ b/Serializing/StackTrace.h @@ -0,0 +1,8 @@ +#ifndef STACK_TRACE_H +#define STACK_TRACE_H + + +void PrintStackTrace(); + + +#endif // STACK_TRACE_H diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/Makefile b/Serializing/Makefile index 2463975..dbbb129 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ -test: test.cpp - g++ test.cpp -o test -std=c++11 +test: test.cpp StackTrace.cpp + g++ -g test.cpp StackTrace.cpp -o test -std=c++11 -rdynamic diff --git a/Serializing/StackTrace.cpp b/Serializing/StackTrace.cpp new file mode 100644 index 0000000..f825b38 --- /dev/null +++ b/Serializing/StackTrace.cpp @@ -0,0 +1,78 @@ +#include "StackTrace.h" +#include +#include + + +#ifdef _WIN32 + +#include "DbgHelp.h" +#include +#pragma comment(lib, "Dbghelp.lib") + +void PrintStackTrace() +{ + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + void* stack[60]; + unsigned short frames = CaptureStackBackTrace(0, 60, stack, NULL); + SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + for(int i = 0; i < frames; i++) + { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + printf("%i: %016I64LX %s - 0x%0X\n", frames - i - 1, stack[i], symbol->Name, symbol->Address); + } + free(symbol); +} + +#else + +#include +#include +#include + +char* SplitStringNext(char* str, char ch) +{ + if (!str) + return 0; + int i = 0; + while (str[i] && str[i] != ch) + i++; + if (!str[i]) + return 0; + str[i] = 0; + return &str[i + 1]; +} + +void PrintStackTrace() +{ +#ifdef USE_PSTACK + if (FILE* f = popen(std::string("pstack " + std::to_string(getpid()) + " | c++filt").c_str(), "r")) + { + char ch; + while (fread(&ch, 1, 1, f) > 0) + std::cout << ch; + pclose(f); + } +#else + void *array[128]; + int size = backtrace(array, 128); + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) + { + // messages[i] looks something like this: "./test(_ZN1DC1Ev+0x18) [0x415974]" + char *progName = messages[i]; + char *funcName = SplitStringNext(progName,'('); + char *offsetStr = SplitStringNext(funcName,'+'); + char *addrStr = SplitStringNext(SplitStringNext(offsetStr, ')'), '['); + char *endStr = SplitStringNext(addrStr,']'); + fprintf(stderr, "[bt]: (%d) %s [%s] %s offset: %s \n", i, progName, addrStr, abi::__cxa_demangle(funcName, 0, 0, 0), offsetStr ); + } + free(messages); +#endif +} + +#endif + + diff --git a/Serializing/StackTrace.h b/Serializing/StackTrace.h new file mode 100644 index 0000000..8153460 --- /dev/null +++ b/Serializing/StackTrace.h @@ -0,0 +1,8 @@ +#ifndef STACK_TRACE_H +#define STACK_TRACE_H + + +void PrintStackTrace(); + + +#endif // STACK_TRACE_H diff --git a/Serializing/XMLVisitor.h b/Serializing/XMLVisitor.h new file mode 100644 index 0000000..929b13f --- /dev/null +++ b/Serializing/XMLVisitor.h @@ -0,0 +1,172 @@ +#ifndef XML_VISITOR_H +#define XML_VISITOR_H + + +class XMLSerializerVisitor : public Serializer +{ +public: + XMLSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + "<" + name + ">\n"; + } + + void Exit(const char* name) + { + output += indent(--depth) + "\n"; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + Visit(var); + Exit(name); + } + + const std::string& Output() + { + output += "\n"; + return output; + } + + void Reset() + { + output = "\n"; + depth = 1; + } + + template + typename std::enable_if< std::is_arithmetic::value >::type + Visit(T& var) + { + output += indent(depth) + std::to_string(var) + "\n"; + } + + template + typename std::enable_if< !std::is_arithmetic::value >::type + Visit(T& var) + { + var.Visit(*this); + } + + template + void Visit(Array& arr) + { + for (auto i : arr) + { + Visit("item", i); + } + } + + void Visit(String& var) + { + // TODO: limitiation is that the string can not have a new line + output += indent(depth) + var + "\n"; + } + +private: + int depth = 0; + std::string output; +}; + + + +class XMLDeserializerVisitor : public Deserializer +{ +public: + XMLDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + String str; + Visit(str); // deserialize the tag + } + + 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) + { + 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) + { + 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); + if (newLineOff != std::string::npos) + var = input.substr(offset, newLineOff-offset); + offset = newLineOff; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + Visit(var); + Exit(name); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +private: + std::string input; + int offset = 0; + void stripWhiteSpace() + { + while (isspace(input.c_str()[offset])) + { + offset++; + } + } +}; + + +#endif // XML_VISITOR_H + + diff --git a/Serializing/JSONVisitor.h b/Serializing/JSONVisitor.h new file mode 100644 index 0000000..528f65c --- /dev/null +++ b/Serializing/JSONVisitor.h @@ -0,0 +1,222 @@ +#ifndef JSON_VISITOR_H +#define JSON_VISITOR_H + + +class JsonSerializerVisitor : public Serializer +{ +public: + JsonSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + quoted(name) + " : {\n"; + } + + 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(var); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + + const std::string& Output() + { + output += "}\n"; + return output; + } + + void Reset() + { + output = "{\n"; + depth = 1; + } +private: + int lastDepth = 0; + int depth = 0; + std::string output; + +}; + + +class JsonDeserializerVisitor : public VisitorBase +{ +public: + JsonDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + 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(var); + + int oldOffset = offset; + ParseString(str); // gets the ',' if there + if (str != ",") + offset = oldOffset; + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +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++; + } + } +}; + + + +#endif // JSON_VISITOR_H + diff --git a/Serializing/Makefile b/Serializing/Makefile index 2463975..dbbb129 100644 --- a/Serializing/Makefile +++ b/Serializing/Makefile @@ -1,6 +1,6 @@ -test: test.cpp - g++ test.cpp -o test -std=c++11 +test: test.cpp StackTrace.cpp + g++ -g test.cpp StackTrace.cpp -o test -std=c++11 -rdynamic diff --git a/Serializing/StackTrace.cpp b/Serializing/StackTrace.cpp new file mode 100644 index 0000000..f825b38 --- /dev/null +++ b/Serializing/StackTrace.cpp @@ -0,0 +1,78 @@ +#include "StackTrace.h" +#include +#include + + +#ifdef _WIN32 + +#include "DbgHelp.h" +#include +#pragma comment(lib, "Dbghelp.lib") + +void PrintStackTrace() +{ + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + void* stack[60]; + unsigned short frames = CaptureStackBackTrace(0, 60, stack, NULL); + SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + for(int i = 0; i < frames; i++) + { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + printf("%i: %016I64LX %s - 0x%0X\n", frames - i - 1, stack[i], symbol->Name, symbol->Address); + } + free(symbol); +} + +#else + +#include +#include +#include + +char* SplitStringNext(char* str, char ch) +{ + if (!str) + return 0; + int i = 0; + while (str[i] && str[i] != ch) + i++; + if (!str[i]) + return 0; + str[i] = 0; + return &str[i + 1]; +} + +void PrintStackTrace() +{ +#ifdef USE_PSTACK + if (FILE* f = popen(std::string("pstack " + std::to_string(getpid()) + " | c++filt").c_str(), "r")) + { + char ch; + while (fread(&ch, 1, 1, f) > 0) + std::cout << ch; + pclose(f); + } +#else + void *array[128]; + int size = backtrace(array, 128); + char** messages = backtrace_symbols(array, size); + for (int i = 0; i < size && messages != NULL; ++i) + { + // messages[i] looks something like this: "./test(_ZN1DC1Ev+0x18) [0x415974]" + char *progName = messages[i]; + char *funcName = SplitStringNext(progName,'('); + char *offsetStr = SplitStringNext(funcName,'+'); + char *addrStr = SplitStringNext(SplitStringNext(offsetStr, ')'), '['); + char *endStr = SplitStringNext(addrStr,']'); + fprintf(stderr, "[bt]: (%d) %s [%s] %s offset: %s \n", i, progName, addrStr, abi::__cxa_demangle(funcName, 0, 0, 0), offsetStr ); + } + free(messages); +#endif +} + +#endif + + diff --git a/Serializing/StackTrace.h b/Serializing/StackTrace.h new file mode 100644 index 0000000..8153460 --- /dev/null +++ b/Serializing/StackTrace.h @@ -0,0 +1,8 @@ +#ifndef STACK_TRACE_H +#define STACK_TRACE_H + + +void PrintStackTrace(); + + +#endif // STACK_TRACE_H diff --git a/Serializing/XMLVisitor.h b/Serializing/XMLVisitor.h new file mode 100644 index 0000000..929b13f --- /dev/null +++ b/Serializing/XMLVisitor.h @@ -0,0 +1,172 @@ +#ifndef XML_VISITOR_H +#define XML_VISITOR_H + + +class XMLSerializerVisitor : public Serializer +{ +public: + XMLSerializerVisitor() + { + Reset(); + } + + void Enter(const char* name) + { + output += indent(depth++) + "<" + name + ">\n"; + } + + void Exit(const char* name) + { + output += indent(--depth) + "\n"; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + Visit(var); + Exit(name); + } + + const std::string& Output() + { + output += "\n"; + return output; + } + + void Reset() + { + output = "\n"; + depth = 1; + } + + template + typename std::enable_if< std::is_arithmetic::value >::type + Visit(T& var) + { + output += indent(depth) + std::to_string(var) + "\n"; + } + + template + typename std::enable_if< !std::is_arithmetic::value >::type + Visit(T& var) + { + var.Visit(*this); + } + + template + void Visit(Array& arr) + { + for (auto i : arr) + { + Visit("item", i); + } + } + + void Visit(String& var) + { + // TODO: limitiation is that the string can not have a new line + output += indent(depth) + var + "\n"; + } + +private: + int depth = 0; + std::string output; +}; + + + +class XMLDeserializerVisitor : public Deserializer +{ +public: + XMLDeserializerVisitor(std::string data) + { + Reset(data); + } + + void Reset(const std::string& a_input) + { + input = a_input; + String str; + Visit(str); // deserialize the tag + } + + 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) + { + 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) + { + 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); + if (newLineOff != std::string::npos) + var = input.substr(offset, newLineOff-offset); + offset = newLineOff; + } + + template + void Visit(const char* name, T& var) + { + Enter(name); + Visit(var); + Exit(name); + } + + template + void Visit(T& var) + { + var.Visit(*this); + } + +private: + std::string input; + int offset = 0; + void stripWhiteSpace() + { + while (isspace(input.c_str()[offset])) + { + offset++; + } + } +}; + + +#endif // XML_VISITOR_H + + diff --git a/Serializing/test.cpp b/Serializing/test.cpp index b849ac0..798334b 100644 --- a/Serializing/test.cpp +++ b/Serializing/test.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include "StackTrace.h" // Some basic types that should build serializable structures from @@ -84,381 +86,10 @@ }; -class XMLSerializerVisitor : public Serializer -{ -public: - XMLSerializerVisitor() - { - Reset(); - } - void Enter(const char* name) - { - output += indent(depth++) + "<" + name + ">\n"; - } +#include "XMLVisitor.h" +#include "JSONVisitor.h" - void Exit(const char* name) - { - output += indent(--depth) + "\n"; - } - - template - void Visit(Array& arr) - { - for (auto i : arr) - { - Visit("item", i); - } - } - - void Visit(Integer32& var) - { - output += indent(depth) + std::to_string(var) + "\n"; - } - - void Visit(String& var) - { - // TODO: limitiation is that the string can not have a new line - output += indent(depth) + var + "\n"; - } - - template - void Visit(const char* name, T& var) - { - Enter(name); - Visit(var); - Exit(name); - } - - template - void Visit(T& var) - { - var.Visit(*this); - } - - const std::string& Output() - { - output += "\n"; - return output; - } - - void Reset() - { - output = ""; - depth = 1; - } - -private: - int depth = 0; - std::string output; -}; - - - -class XMLDeserializerVisitor : public Deserializer -{ -public: - XMLDeserializerVisitor(std::string data) - { - Reset(data); - } - - void Reset(const std::string& a_input) - { - input = a_input; - String str; - Visit(str); // deserialize the tag - } - - 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) - { - 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) - { - 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); - if (newLineOff != std::string::npos) - var = input.substr(offset, newLineOff-offset); - offset = newLineOff; - } - - template - void Visit(const char* name, T& var) - { - Enter(name); - Visit(var); - Exit(name); - } - - template - void Visit(T& var) - { - var.Visit(*this); - } - -private: - std::string input; - int offset = 0; - void stripWhiteSpace() - { - while (isspace(input.c_str()[offset])) - { - offset++; - } - } -}; - - -class JsonSerializerVisitor : public Serializer -{ -public: - JsonSerializerVisitor() - { - Reset(); - } - - void Enter(const char* name) - { - output += indent(depth++) + quoted(name) + " : {\n"; - } - - 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(var); - } - - template - void Visit(T& var) - { - var.Visit(*this); - } - - const std::string& Output() - { - output += "}\n"; - return output; - } - - void Reset() - { - output = "{\n"; - depth = 1; - } -private: - int lastDepth = 0; - int depth = 0; - std::string output; - -}; - - -class JsonDeserializerVisitor : public VisitorBase -{ -public: - JsonDeserializerVisitor(std::string data) - { - Reset(data); - } - - void Reset(const std::string& a_input) - { - input = a_input; - 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(var); - - int oldOffset = offset; - ParseString(str); // gets the ',' if there - if (str != ",") - offset = oldOffset; - } - - template - void Visit(T& var) - { - var.Visit(*this); - } - -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++; - } - } -}; @@ -503,7 +134,7 @@ }; */ -/* + struct Property { Property() : m_type(PT_Invalid) {} @@ -520,6 +151,7 @@ explicit Property(Float64 a_flt64 ) : m_type(PT_Float64 ) { m_basicType.m_flt64 = a_flt64 ; } explicit Property(const Array& a_array ) : m_type(PT_Array ) { m_array = a_array ; } explicit Property(const String& a_string) : m_type(PT_String) { m_string = a_string; } + explicit Property(const char* a_string) : m_type(PT_String) { m_string = a_string; } enum PropertyType { @@ -594,11 +226,208 @@ v.Exit("Property"); } }; + + +struct f_any +{ + f_any() : ptr() {} + ~f_any() { delete ptr; } + bool valid() const { return ptr != 0; } + void f() { assert(ptr); ptr->f(); } + + struct placeholder + { + virtual ~placeholder() {} + virtual void f() const = 0; + }; + + template < typename T > + struct impl : placeholder + { + impl(T const& t) : val(t) {} + void f() const { val.f(); } + T val; + }; + // ptr can now point to the entire family of + // struct types generated from impl + placeholder * ptr; + + template < typename T > + f_any(T const& t) : ptr(new impl(t)) {} + + // assignment, etc... +}; + +template +struct static_constructor +{ + struct constructor { constructor() { ctor(); } }; + static constructor c; +}; +template +typename static_constructor::constructor static_constructor::c; + + + +typedef void*(*getter)(void*); + +struct VisitorAttribute +{ + VisitorAttribute(const char* name, getter a_getter) : m_name(name), m_getter(a_getter) {} + const char* m_name; + getter m_getter; +}; + +template +struct BaseType +{ +protected: + typedef T _this_type; + static std::vector& _this_members() { static std::vector _s_this_members; return _s_this_members; } + static void AddMember(const char* a_name, getter a_func) { _this_members().push_back(VisitorAttribute(a_name, a_func)); } +}; + +/* +template +struct TypeWrapper +{ + T m_value; +protected: + typedef T _wrapped_type; + static const char* _wrapped_name() { return "#name"; } + static type& get(void* _this) { return ((parent*)_this)->name; } + static void run_once() { static_constructor<&run_once>::c; parent::AddMember(_wrapped_name(), (getter)&tmp_getter_##name); } +}; */ +#include +#include +#include + +template +inline typename std::enable_if::type +for_each(V& v, T obj, std::tuple &) // Unused arguments are given no names. +{ } + +template +inline typename std::enable_if::type +for_each(V& v, T obj, std::tuple& t) +{ + v.Visit(std::get(t), std::get(t)(obj)); + for_each(v, obj, t); +} + +#define DECLARE_STRUCT(name) \ + class name : public BaseType { \ + static const char* _this_name() { return #name; } \ + public: \ + std::tuple m_tup; \ + typedef struct { static decltype(std::make_tuple()) tuple() { return std::make_tuple(); } + + +#define DECLARE_MEMBER(type, name, ...) \ + } blah##name; \ + static type& tmp_getter_##name(void* _this) { return ((_this_type*)_this)->name; } \ + static void tmp_collect_##name() { static_constructor<&tmp_collect_##name>::c; AddMember(#name, (getter)&tmp_getter_##name); } \ + /*static auto get_tuple_for_##name() { static auto s_tuple = std::make_tuple(1,1); return s_tuple; }*/ \ + type name = type(__VA_ARGS__); \ + typedef struct { static decltype(std::tuple_cat(blah##name::tuple(), std::make_tuple(#name, tmp_getter_##name))) tuple() { return std::tuple_cat(blah##name::tuple(), std::make_tuple(#name, tmp_getter_##name)); } + + +#define END_STRUCT(name) \ + } last; \ + template \ + void Visit(V& v) \ + { \ + v.Enter(_this_name()); \ + auto tup = last::tuple(); \ + for_each(v, this, tup); \ + /*for (auto i: _this_members())*/ \ + /* v.Visit(i.m_name, *(int*)i.m_getter(this));*/ \ + v.Exit(_this_name()); \ + } \ + }; + + + +DECLARE_STRUCT(TestStruct) +DECLARE_MEMBER(int, m_int, 9) +DECLARE_MEMBER(bool, m_bool, false) +END_STRUCT(TestStruct) + + + +#include +#include +#include +#include + +struct A { + A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; } + A(int& n) { std::cout << "lvalue overload, n=" << n << "\n"; } + A(const char*& n) { std::cout << "lvalue str overload, n=" << n << "\n"; } + A(const char*&& n) { std::cout << "rvalue str overload, n=" << n << "\n"; } +}; + +template +std::unique_ptr make_unique1(U&& u) +{ + return std::unique_ptr(new T(std::forward(u))); +} + + +#include +#include +#include +#include + + + +class Z { public: Z() { PrintStackTrace(); } }; +class B { public: B() { Z z; } }; +class C { public: C() { B b; } }; +class D { public: D() { C c; } }; int main(int argc, char* argv[]) { + auto p1 = make_unique1(2); // rvalue + int i = 1; + auto p2 = make_unique1(i); // lvalue + auto p3 = make_unique1("blah"); // rvalue + const char *i2 = "foo"; + auto p4 = make_unique1(i2); // lvalue + + + typedef struct { static decltype(std::make_tuple()) tuple() { return std::make_tuple(); } + } blah_name1; typedef struct { static decltype(std::tuple_cat(blah_name1::tuple(), std::make_tuple("x", 1))) tuple() { return std::tuple_cat(blah_name1::tuple(), std::make_tuple("x", 1)); } + } blah_name2; typedef struct { static decltype(std::tuple_cat(blah_name2::tuple(), std::make_tuple("xb", true))) tuple() { return std::tuple_cat(blah_name2::tuple(), std::make_tuple("xb", true)); } + } blah_name3; typedef struct { static decltype(std::tuple_cat(blah_name3::tuple(), std::make_tuple("y", 2))) tuple() { return std::tuple_cat(blah_name3::tuple(), std::make_tuple("y", 2)); } + } blah_name4; typedef struct { static decltype(std::tuple_cat(blah_name4::tuple(), std::make_tuple("x", false))) tuple() { return std::tuple_cat(blah_name4::tuple(), std::make_tuple("yb", false)); } + } blah_name5; typedef struct { static decltype(std::tuple_cat(blah_name5::tuple(), std::make_tuple("z", 3))) tuple() { return std::tuple_cat(blah_name5::tuple(), std::make_tuple("z", 3)); } + } blah_name6; typedef struct { static decltype(std::tuple_cat(blah_name6::tuple(), std::make_tuple("zb", true))) tuple() { return std::tuple_cat(blah_name6::tuple(), std::make_tuple("zb", true)); } + } last; + + std::cout << "mangled: " << typeid(last::tuple()).name() << std::endl; + std::cout << "demangled: " << abi::__cxa_demangle(typeid(last::tuple()).name(), 0, 0, 0) << std::endl; + + D stack; + + XMLSerializerVisitor serializer; + printf("%s", serializer.Output().c_str()); + + { + TestStruct t; +// t.m_int = 1234; +// t.m_bool = true; + + XMLSerializerVisitor serializer; + serializer.Visit(t); + printf("%s", serializer.Output().c_str()); + } + + + return 0; + std::string input; { @@ -655,7 +484,7 @@ printf("%s", serializer.Output().c_str()); } } -/* + { Property p("hello world"); Property i(100); @@ -664,12 +493,12 @@ vals.push_back(i); Property a(vals); - JsonSerializerVisitor serializer; + XMLSerializerVisitor serializer; serializer.Visit(a); printf("%s", serializer.Output().c_str()); input = serializer.Output(); } -*/ + }