Finalizing state to/from XML encoding and decoding
diff --git a/model/sync-state.cc b/model/sync-state.cc
index 268a45f..5e09655 100644
--- a/model/sync-state.cc
+++ b/model/sync-state.cc
@@ -21,8 +21,102 @@
*/
#include "sync-state.h"
+#include "sync-diff-leaf.h"
+#include "sync-std-name-info.h"
+
#include <boost/assert.hpp>
+#include <boost/foreach.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/lexical_cast.hpp>
+
+#define TIXML_USE_STL
+#include <tinyxml.h>
+
+using namespace std;
+using namespace boost;
+
+typedef error_info<struct tag_errmsg, string> info_str;
namespace Sync {
+#ifdef _DEBUG
+#define DEBUG_ENDL os << "\n";
+#else
+#define DEBUG_ENDL
+#endif
+
+std::ostream &
+operator << (std::ostream &os, const State &state)
+{
+ os << "<state>"; DEBUG_ENDL;
+
+ BOOST_FOREACH (shared_ptr<const Leaf> leaf, state.getLeaves ().get<ordered> ())
+ {
+ shared_ptr<const DiffLeaf> diffLeaf = dynamic_pointer_cast<const DiffLeaf> (leaf);
+ if (diffLeaf != 0)
+ {
+ os << "<item action=\"" << diffLeaf->getOperation () << "\">"; DEBUG_ENDL;
+ }
+ else
+ {
+ os << "<item>"; DEBUG_ENDL;
+ }
+ os << "<name>" << leaf->getInfo () << "</name>"; DEBUG_ENDL;
+ if (diffLeaf == 0 || (diffLeaf != 0 && diffLeaf->getOperation () == UPDATE))
+ {
+ os << "<seq>" << leaf->getSeq () << "</seq>"; DEBUG_ENDL;
+ }
+ os << "</item>"; DEBUG_ENDL;
+ }
+ os << "</state>";
+}
+
+std::istream &
+operator >> (std::istream &in, State &state)
+{
+ TiXmlDocument doc;
+ in >> doc;
+
+ if (doc.RootElement() == 0)
+ BOOST_THROW_EXCEPTION (SyncXmlDecodingFailure () << info_str ("Empty XML"));
+
+ for (TiXmlElement *iterator = doc.RootElement()->FirstChildElement ("item");
+ iterator != 0;
+ iterator = iterator->NextSiblingElement("item"))
+ {
+ TiXmlElement *name = iterator->FirstChildElement ("name");
+ if (name == 0 || name->GetText() == 0)
+ BOOST_THROW_EXCEPTION (SyncXmlDecodingFailure () << info_str ("<name> element is missing"));
+
+ NameInfoConstPtr info = StdNameInfo::FindOrCreate (name->GetText());
+
+ if (iterator->Attribute("action") == 0 || strcmp(iterator->Attribute("action"), "update") == 0)
+ {
+ TiXmlElement *seq = iterator->FirstChildElement ("seq");
+ if (seq == 0)
+ BOOST_THROW_EXCEPTION (SyncXmlDecodingFailure () << info_str ("<seq> element is missing"));
+
+ TiXmlElement *session = seq->FirstChildElement ("session");
+ TiXmlElement *seqno = seq->FirstChildElement ("seqno");
+
+ if (session == 0 || session->GetText() == 0)
+ BOOST_THROW_EXCEPTION (SyncXmlDecodingFailure () << info_str ("<session> element is missing"));
+ if (seqno == 0 || seqno->GetText() == 0)
+ BOOST_THROW_EXCEPTION (SyncXmlDecodingFailure () << info_str ("<seqno> element is missing"));
+
+ state.update (info, SeqNo (
+ lexical_cast<uint32_t> (session->GetText()),
+ lexical_cast<uint32_t> (seqno->GetText())
+ ));
+ }
+ else
+ {
+ state.remove (info);
+ }
+ }
+
+ return in;
+}
+
}