Audacity  3.0.3
XMLFileReader.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  XMLFileReader.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//*******************************************************************/
15 
16 #include "XMLFileReader.h"
17 
18 #include <wx/defs.h>
19 #include <wx/ffile.h>
20 #include <wx/intl.h>
21 #include <wx/log.h>
22 
23 #include <string.h>
24 
25 #include "expat.h"
26 
28 {
29  mParser = XML_ParserCreate(NULL);
30  XML_SetUserData(mParser, (void *)this);
31  XML_SetElementHandler(mParser, startElement, endElement);
32  XML_SetCharacterDataHandler(mParser, charHandler);
33  mBaseHandler = NULL;
34  mHandler.reserve(128);
35 }
36 
38 {
39  XML_ParserFree(mParser);
40 }
41 
43  const FilePath &fname)
44 {
45  wxFFile theXMLFile(fname, wxT("rb"));
46  if (!theXMLFile.IsOpened()) {
47  mErrorStr = XO("Could not open file: \"%s\"").Format( fname );
48  return false;
49  }
50 
51  mBaseHandler = baseHandler;
52 
53  const size_t bufferSize = 16384;
54  char buffer[16384];
55  int done = 0;
56  do {
57  size_t len = fread(buffer, 1, bufferSize, theXMLFile.fp());
58  done = (len < bufferSize);
59  if (!XML_Parse(mParser, buffer, len, done)) {
60 
61  // Embedded error string from expat doesn't translate (yet)
62  // We could make a table of XOs if we wanted so that it could
63  // If we do, uncomment the second constructor argument so it's not
64  // a verbatim string
66  XML_ErrorString(XML_GetErrorCode(mParser)) // , {}
67  );
68 
69  mErrorStr = XO("Error: %s at line %lu").Format(
71  (long unsigned int)XML_GetCurrentLineNumber(mParser)
72  );
73 
74  theXMLFile.Close();
75  return false;
76 
77 // If we did want to handle every single parse error, these are they....
78 /*
79  XML_L("out of memory"),
80  XML_L("syntax error"),
81  XML_L("no element found"),
82  XML_L("not well-formed (invalid token)"),
83  XML_L("unclosed token"),
84  XML_L("partial character"),
85  XML_L("mismatched tag"),
86  XML_L("duplicate attribute"),
87  XML_L("junk after document element"),
88  XML_L("illegal parameter entity reference"),
89  XML_L("undefined entity"),
90  XML_L("recursive entity reference"),
91  XML_L("asynchronous entity"),
92  XML_L("reference to invalid character number"),
93  XML_L("reference to binary entity"),
94  XML_L("reference to external entity in attribute"),
95  XML_L("XML or text declaration not at start of entity"),
96  XML_L("unknown encoding"),
97  XML_L("encoding specified in XML declaration is incorrect"),
98  XML_L("unclosed CDATA section"),
99  XML_L("error in processing external entity reference"),
100  XML_L("document is not standalone"),
101  XML_L("unexpected parser state - please send a bug report"),
102  XML_L("entity declared in parameter entity"),
103  XML_L("requested feature requires XML_DTD support in Expat"),
104  XML_L("cannot change setting once parsing has begun"),
105  XML_L("unbound prefix"),
106  XML_L("must not undeclare prefix"),
107  XML_L("incomplete markup in parameter entity"),
108  XML_L("XML declaration not well-formed"),
109  XML_L("text declaration not well-formed"),
110  XML_L("illegal character(s) in public id"),
111  XML_L("parser suspended"),
112  XML_L("parser not suspended"),
113  XML_L("parsing aborted"),
114  XML_L("parsing finished"),
115  XML_L("cannot suspend in external parameter entity"),
116  XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
117  XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
118  XML_L("prefix must not be bound to one of the reserved namespace names")
119 */
120  }
121  } while (!done);
122 
123  theXMLFile.Close();
124 
125  // Even though there were no parse errors, we only succeed if
126  // the first-level handler actually got called, and didn't
127  // return false.
128  if (mBaseHandler)
129  return true;
130  else {
131  mErrorStr = XO("Could not load file: \"%s\"").Format( fname );
132  return false;
133  }
134 }
135 
137  const wxString &xmldata)
138 {
139  auto utf8 = xmldata.ToUTF8();
140  const char *buffer = utf8.data();
141  int len = utf8.length();
142 
143  mBaseHandler = baseHandler;
144 
145  if (!XML_Parse(mParser, buffer, len, true))
146  {
147 
148  // Embedded error string from expat doesn't translate (yet)
149  // We could make a table of XOs if we wanted so that it could
150  // If we do, uncomment the second constructor argument so it's not
151  // a verbatim string
153  XML_ErrorString(XML_GetErrorCode(mParser)) // , {}
154  );
155 
156  mErrorStr = XO("Error: %s at line %lu").Format(
158  (long unsigned int)XML_GetCurrentLineNumber(mParser)
159  );
160 
161  wxLogMessage(wxT("ParseString error: %s\n===begin===%s\n===end==="), mErrorStr.Debug(), buffer);
162 
163  return false;
164  }
165 
166  // Even though there were no parse errors, we only succeed if
167  // the first-level handler actually got called, and didn't
168  // return false.
169  if (!mBaseHandler)
170  {
171  mErrorStr = XO("Could not parse XML");
172  return false;
173  }
174 
175  return true;
176 }
177 
179 {
180  return mErrorStr;
181 }
182 
184 {
185  return mLibraryErrorStr;
186 }
187 
188 // static
189 void XMLFileReader::startElement(void *userData, const char *name,
190  const char **atts)
191 {
192  XMLFileReader *This = (XMLFileReader *)userData;
193  Handlers &handlers = This->mHandler;
194 
195  if (handlers.empty()) {
196  handlers.push_back(This->mBaseHandler);
197  }
198  else {
199  if (XMLTagHandler *const handler = handlers.back())
200  handlers.push_back(handler->ReadXMLChild(name));
201  else
202  handlers.push_back(NULL);
203  }
204 
205  if (XMLTagHandler *& handler = handlers.back()) {
206  if (!handler->ReadXMLTag(name, atts)) {
207  handler = nullptr;
208  if (handlers.size() == 1)
209  This->mBaseHandler = nullptr;
210  }
211  }
212 }
213 
214 // static
215 void XMLFileReader::endElement(void *userData, const char *name)
216 {
217  XMLFileReader *This = (XMLFileReader *)userData;
218  Handlers &handlers = This->mHandler;
219 
220  if (XMLTagHandler *const handler = handlers.back())
221  handler->ReadXMLEndTag(name);
222 
223  handlers.pop_back();
224 }
225 
226 // static
227 void XMLFileReader::charHandler(void *userData, const char *s, int len)
228 {
229  XMLFileReader *This = (XMLFileReader *)userData;
230  Handlers &handlers = This->mHandler;
231 
232  if (XMLTagHandler *const handler = handlers.back())
233  handler->ReadXMLContent(s, len);
234 }
XMLFileReader::GetLibraryErrorStr
const TranslatableString & GetLibraryErrorStr() const
Definition: XMLFileReader.cpp:183
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
XO
#define XO(s)
Definition: Internat.h:31
XMLFileReader::XMLFileReader
XMLFileReader()
Definition: XMLFileReader.cpp:27
XMLFileReader::~XMLFileReader
~XMLFileReader()
Definition: XMLFileReader.cpp:37
TranslatableString::Debug
wxString Debug() const
Format as an English string for debugging logs and developers' eyes, not for end users.
Definition: TranslatableString.h:82
XMLFileReader::mHandler
Handlers mHandler
Definition: XMLFileReader.h:44
XMLFileReader::Parse
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Definition: XMLFileReader.cpp:42
XMLFileReader::charHandler
static void charHandler(void *userData, const char *s, int len)
Definition: XMLFileReader.cpp:227
XMLFileReader::GetErrorStr
const TranslatableString & GetErrorStr() const
Definition: XMLFileReader.cpp:178
FilePath
wxString FilePath
Definition: Project.h:20
XMLFileReader::Handlers
std::vector< XMLTagHandler * > Handlers
Definition: XMLFileReader.h:43
XMLFileReader::mErrorStr
TranslatableString mErrorStr
Definition: XMLFileReader.h:45
XMLFileReader::ParseString
bool ParseString(XMLTagHandler *baseHandler, const wxString &xmldata)
Definition: XMLFileReader.cpp:136
name
const TranslatableString name
Definition: Distortion.cpp:98
XMLFileReader.h
XMLFileReader::mBaseHandler
XMLTagHandler * mBaseHandler
Definition: XMLFileReader.h:42
XMLTagHandler
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:62
XMLFileReader::endElement
static void endElement(void *userData, const char *name)
Definition: XMLFileReader.cpp:215
XMLFileReader
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:18
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
XMLFileReader::mParser
XML_Parser mParser
Definition: XMLFileReader.h:41
XMLFileReader::startElement
static void startElement(void *userData, const char *name, const char **atts)
Definition: XMLFileReader.cpp:189
XMLFileReader::mLibraryErrorStr
TranslatableString mLibraryErrorStr
Definition: XMLFileReader.h:46