#include "era/xml_format.h" #include "base/indented_stream.h" #include "base/xml_utils.h" using namespace boost; using namespace era; using namespace persistent_data; using namespace std; using namespace xml_utils; //---------------------------------------------------------------- namespace { class xml_emitter : public emitter { public: xml_emitter(ostream &out) : out_(out) { } void begin_superblock(std::string const &uuid, uint32_t block_size, pd::block_address nr_blocks, uint32_t current_era) { out_.indent(); out_ << ""; out_ << endl; out_.inc(); } void end_superblock() { out_.dec(); out_.indent(); out_ << "" << endl; } void begin_writeset(uint32_t era, uint32_t nr_bits) { out_.indent(); out_ << "" << endl; out_.inc(); } void writeset_bit(uint32_t bit, bool value) { out_.indent(); // FIXME: collect all the bits, then uuencode out_ << "" << endl; } void end_writeset() { out_.dec(); out_.indent(); out_ << "" << endl; } void begin_era_array() { out_.indent(); out_ << "" << endl; out_.inc(); } void era(pd::block_address block, uint32_t era) { out_.indent(); out_ << "" << endl; } void end_era_array() { out_.dec(); out_.indent(); out_ << "" << endl; } char const *truth_value(bool v) const { return v ? "true" : "false"; } private: indented_stream out_; }; //-------------------------------- // Parser //-------------------------------- void parse_bit(attributes const &a, emitter *e) { bool value; string txt = get_attr(a, "value"); if (txt == "true") value = true; else if (txt == "false") value = false; else throw runtime_error("invalid boolean"); e->writeset_bit(get_attr(a, "block"), value); } void start_tag(void *data, char const *el, char const **attr) { emitter *e = static_cast(data); attributes a; build_attributes(a, attr); if (!strcmp(el, "superblock")) e->begin_superblock(get_attr(a, "uuid"), get_attr(a, "block_size"), get_attr(a, "nr_blocks"), get_attr(a, "current_era")); else if (!strcmp(el, "writeset")) e->begin_writeset(get_attr(a, "era"), get_attr(a, "nr_bits")); else if (!strcmp(el, "bit")) parse_bit(a, e); else if (!strcmp(el, "era_array")) e->begin_era_array(); else if (!strcmp(el, "era")) e->era(get_attr(a, "block"), get_attr(a, "era")); else throw runtime_error("unknown tag type"); } void end_tag(void *data, const char *el) { emitter *e = static_cast(data); if (!strcmp(el, "superblock")) e->end_superblock(); else if (!strcmp(el, "writeset")) e->end_writeset(); else if (!strcmp(el, "era_array")) e->end_era_array(); else if (!strcmp(el, "era")) /* do nothing */ ; else if (!strcmp(el, "bit")) /* do nothing */ ; else throw runtime_error("unknown tag type"); } } //---------------------------------------------------------------- emitter::ptr era::create_xml_emitter(std::ostream &out) { return emitter::ptr(new xml_emitter(out)); } void era::parse_xml(std::string const &backup_file, emitter::ptr e, bool quiet) { xml_parser p; XML_SetUserData(p.get_parser(), e.get()); XML_SetElementHandler(p.get_parser(), start_tag, end_tag); p.parse(backup_file, quiet); } //----------------------------------------------------------------