#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) + "</" + name + ">\n";
}
template <class T>
void Visit(const char* name, T& var)
{
Enter(name);
Visit(var);
Exit(name);
}
const std::string& Output()
{
output += "</xml>\n";
return output;
}
void Reset()
{
output = "<xml>\n";
depth = 1;
}
template <typename T>
typename std::enable_if< std::is_arithmetic<T>::value >::type
Visit(T& var)
{
output += indent(depth) + std::to_string(var) + "\n";
}
template <class T>
typename std::enable_if< !std::is_arithmetic<T>::value >::type
Visit(T& var)
{
var.Visit(*this);
}
template <class T>
void Visit(Array<T>& 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 <xml> 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 <class T>
void Visit(Array<T>& arr)
{
while (true)
{
int oldOffset = offset;
String str;
Visit(str);
offset = oldOffset;
if (str != "<item>")
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 <class T>
void Visit(const char* name, T& var)
{
Enter(name);
Visit(var);
Exit(name);
}
template <class T>
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