#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 <class T>
void Visit(Array<T>& 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 <class T>
void Visit(const char* name, T& var)
{
if (lastDepth == depth)
output += " ,\n";
lastDepth = depth;
output += indent(depth) + quoted(name) + " : ";
Visit(var);
}
template <class T>
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 <class T>
void Visit(Array<T>& 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 <class T>
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 <class T>
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