openMSX
XMLLoader.cc
Go to the documentation of this file.
1 #include "XMLLoader.hh"
2 #include "XMLElement.hh"
3 #include "XMLException.hh"
4 #include "File.hh"
5 #include "FileException.hh"
6 #include "MemBuffer.hh"
7 #include "rapidsax.hh"
8 
9 namespace openmsx {
10 namespace XMLLoader {
11 
13 {
14 public:
15  // rapidsax handler interface
16  void start(string_view name);
17  void attribute(string_view name, string_view value);
18  void text(string_view txt);
19  void stop();
20  void doctype(string_view txt);
21 
22  string_view getSystemID() const { return systemID; }
23  XMLElement& getRoot() { return root; }
24 
25 private:
26  XMLElement root;
27  std::vector<XMLElement*> current;
28  string_view systemID;
29 };
30 
32 {
33  MemBuffer<char> buf;
34  try {
35  File file(filename);
36  auto size = file.getSize();
37  buf.resize(size + rapidsax::EXTRA_BUFFER_SPACE);
38  file.read(buf.data(), size);
39  buf[size] = 0;
40  } catch (FileException& e) {
41  throw XMLException(filename, ": failed to read: ", e.getMessage());
42  }
43 
44  XMLElementParser handler;
45  try {
46  rapidsax::parse<rapidsax::trimWhitespace>(handler, buf.data());
47  } catch (rapidsax::ParseError& e) {
48  throw XMLException(filename, ": Document parsing failed: ", e.what());
49  }
50  auto& root = handler.getRoot();
51  if (root.getName().empty()) {
52  throw XMLException(filename,
53  ": Document doesn't contain mandatory root Element");
54  }
55  if (handler.getSystemID().empty()) {
56  throw XMLException(filename, ": Missing systemID.\n"
57  "You're probably using an old incompatible file format.");
58  }
59  if (handler.getSystemID() != systemID) {
60  throw XMLException(filename, ": systemID doesn't match "
61  "(expected ", systemID, ", got ", handler.getSystemID(), ")\n"
62  "You're probably using an old incompatible file format.");
63  }
64  return std::move(root);
65 }
66 
68 {
69  XMLElement* newElem;
70  if (!current.empty()) {
71  newElem = &current.back()->addChild(name);
72  } else {
73  root.setName(name);
74  newElem = &root;
75  }
76  current.push_back(newElem);
77 }
78 
80 {
81  if (current.back()->hasAttribute(name)) {
82  throw XMLException(
83  "Found duplicate attribute \"", name, "\" in <",
84  current.back()->getName(), ">.");
85  }
86  current.back()->addAttribute(name, value);
87 }
88 
90 {
91  if (current.back()->hasChildren()) {
92  // no mixed-content elements
93  throw XMLException(
94  "Mixed text+subtags in <", current.back()->getName(),
95  ">: \"", txt, "\".");
96  }
97  current.back()->setData(txt);
98 }
99 
101 {
102  current.pop_back();
103 }
104 
106 {
107  auto pos1 = txt.find(" SYSTEM ");
108  if (pos1 == string_view::npos) return;
109  if ((pos1 + 8) >= txt.size()) return;
110  char q = txt[pos1 + 8];
111  if ((q != '"') && (q != '\'')) return;
112  auto t = txt.substr(pos1 + 9);
113  auto pos2 = t.find(q);
114  if (pos2 == string_view::npos) return;
115 
116  systemID = t.substr(0, pos2);
117 }
118 
119 } // namespace XMLLoader
120 } // namespace openmsx
void doctype(string_view txt)
Definition: XMLLoader.cc:105
size_t getSize()
Returns the size of this file.
Definition: File.cc:99
const std::string & getMessage() const &
Definition: MSXException.hh:23
void start(string_view name)
Definition: XMLLoader.cc:67
void text(string_view txt)
Definition: XMLLoader.cc:89
void setName(string_view name)
Definition: XMLElement.cc:81
string_view getSystemID() const
Definition: XMLLoader.cc:22
static const size_type npos
Definition: string_view.hh:23
size_t size(string_view utf8)
void resize(size_t size)
Grow or shrink the memory block.
Definition: MemBuffer.hh:120
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:90
size_type find(string_view s) const
Definition: string_view.cc:38
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
XMLElement load(string_view filename, string_view systemID)
Definition: XMLLoader.cc:31
This class implements a (close approximation) of the std::string_view class.
Definition: string_view.hh:15
string_view substr(size_type pos, size_type n=npos) const
Definition: string_view.cc:32
size_type size() const
Definition: string_view.hh:52
void attribute(string_view name, string_view value)
Definition: XMLLoader.cc:79
void read(void *buffer, size_t num)
Read from file.
Definition: File.cc:79
const char * what() const
Definition: rapidsax.hh:110