diff --git a/Makefile.in b/Makefile.in index eb6ecde..ab9837c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -411,7 +411,7 @@ ERA_DUMP_OBJECTS=$(subst .cc,.o,$(ERA_DUMP_SOURCE)) era_dump: $(ERA_DUMP_OBJECTS) era/era_dump.o @echo " [LD] $@" - $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) + $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) ERA_INVALIDATE_SOURCE=\ block-cache/block_cache.cc \ @@ -445,7 +445,7 @@ ERA_INVALIDATE_OBJECTS=$(subst .cc,.o,$(ERA_INVALIDATE_SOURCE)) era_invalidate: $(ERA_INVALIDATE_OBJECTS) era/era_invalidate.o @echo " [LD] $@" - $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) + $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) #---------------------------------------------------------------- diff --git a/era/xml_format.cc b/era/xml_format.cc index 0878410..0112aae 100644 --- a/era/xml_format.cc +++ b/era/xml_format.cc @@ -1,11 +1,15 @@ #include "era/xml_format.h" #include "base/indented_stream.h" +#include "base/xml_utils.h" + +#include using namespace boost; using namespace era; using namespace persistent_data; using namespace std; +using namespace xml_utils; //---------------------------------------------------------------- @@ -75,6 +79,56 @@ namespace { private: indented_stream out_; }; + + //-------------------------------- + // Parser + //-------------------------------- + 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")) + e->writeset_bit(get_attr(a, "bit"), + get_attr(a, "value")); + + 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 + throw runtime_error("unknown tag type"); + } } //---------------------------------------------------------------- @@ -85,4 +139,32 @@ era::create_xml_emitter(std::ostream &out) return emitter::ptr(new xml_emitter(out)); } +void +era::parse_xml(std::istream &in, emitter::ptr e) +{ + XML_Parser parser = XML_ParserCreate(NULL); + if (!parser) + throw runtime_error("couldn't create xml parser"); + + XML_SetUserData(parser, e.get()); + XML_SetElementHandler(parser, start_tag, end_tag); + + while (!in.eof()) { + char buffer[4096]; + in.read(buffer, sizeof(buffer)); + size_t len = in.gcount(); + int done = in.eof(); + + if (!XML_Parse(parser, buffer, len, done)) { + ostringstream out; + out << "Parse error at line " + << XML_GetCurrentLineNumber(parser) + << ":\n" + << XML_ErrorString(XML_GetErrorCode(parser)) + << endl; + throw runtime_error(out.str()); + } + } +} + //----------------------------------------------------------------