34 #define vsnprintf _vsnprintf 38 #include "AISDatabaseParser.h" 46 static const not_used
char *states[] =
69 AISDatabaseParser::aisStartDocument(AISParserState *state)
71 state->state = PARSER_START;
72 state->unknown_depth = 0;
73 state->prev_state = PARSER_UNKNOWN;
74 state->error_msg =
"";
76 DBG2(cerr <<
"Parser state: " << states[state->state] << endl);
82 AISDatabaseParser::aisEndDocument(AISParserState *state)
84 DBG2(cerr <<
"Ending state == " << states[state->state] << endl);
86 if (state->unknown_depth != 0) {
87 AISDatabaseParser::aisFatalError(state,
"The document contained unbalanced tags.");
89 DBG(cerr <<
"unknown_depth != 0 (" << state->unknown_depth <<
")" 103 AISDatabaseParser::aisStartElement(AISParserState *state,
const char *name,
106 switch (state->state) {
108 if (strcmp(name,
"ais") != 0) {
109 DBG(cerr <<
"Expecting ais. Got " << name << endl);
118 if (strcmp(name,
"entry") == 0) {
119 state->prev_state = state->state;
120 state->state = ENTRY;
123 state->prev_state = state->state;
124 state->state = PARSER_UNKNOWN;
125 state->unknown_depth++;
130 if (strcmp(name,
"primary") == 0) {
131 state->prev_state = state->state;
132 state->state = PRIMARY;
135 if (strcmp(attrs[0],
"url") == 0) {
136 state->regexp =
false;
137 state->primary = attrs[1];
139 else if (strcmp(attrs[0],
"regexp") == 0) {
140 state->regexp =
true;
141 state->primary = attrs[1];
145 AISDatabaseParser::aisFatalError(state,
"Required attribute 'url' or 'regexp' missing from element 'primary'.");
149 else if (strcmp(name,
"ancillary") == 0) {
150 state->prev_state = state->state;
151 state->state = ANCILLARY;
154 string rule =
"overwrite";
155 for (
int i = 0; attrs && attrs[i] != 0; i = i + 2) {
156 if (strcmp(attrs[i],
"url") == 0)
158 else if (strcmp(attrs[i],
"rule") == 0)
165 AISDatabaseParser::aisFatalError(state,
"Required attribute 'url' missing from element 'ancillary'.");
169 if (rule !=
"overwrite" && rule !=
"replace" && rule !=
"fallback") {
170 string msg = string(
"Optional attribute 'rule' in element 'ancillary' has a bad value: ") + rule +
"\nIt should be one of 'overwrite', 'replace' or 'fallback'.";
171 AISDatabaseParser::aisFatalError(state, msg.c_str());
176 state->rv.push_back(r);
179 state->prev_state = state->state;
180 state->state = PARSER_UNKNOWN;
181 state->unknown_depth++;
192 state->unknown_depth++;
199 DBG2(cerr <<
"Start element " << name <<
" (state " 200 << states[state->state] <<
")" << endl);
211 AISDatabaseParser::aisEndElement(AISParserState *state,
const char *)
213 DBG2(cerr <<
"End element: state " << states[state->state] << endl);
215 switch (state->state) {
217 state->prev_state = state->state;
218 state->state = PARSER_FINISH;
222 state->prev_state = state->state;
227 state->ais->add_regexp_resource(state->primary, state->rv);
229 state->ais->add_url_resource(state->primary, state->rv);
232 state->rv.erase(state->rv.begin(), state->rv.end());
236 state->prev_state = state->state;
237 state->state = ENTRY;
241 state->prev_state = state->state;
242 state->state = ENTRY;
247 state->unknown_depth--;
262 AISDatabaseParser::aisGetEntity(AISParserState *,
const xmlChar *name)
264 return xmlGetPredefinedEntity(name);
272 AISDatabaseParser::aisWarning(AISParserState *state,
const char *msg, ...)
276 state->state = PARSER_ERROR;
280 vsnprintf(str, 1024, msg, args);
285 int line = xmlSAX2GetLineNumber(state->ctxt);
287 int line = getLineNumber(state->ctxt);
289 state->error_msg +=
"At line: " + long_to_string(line) +
": ";
290 state->error_msg += string(str) + string(
"\n");
298 AISDatabaseParser::aisError(AISParserState *state,
const char *msg, ...)
302 state->state = PARSER_ERROR;
306 vsnprintf(str, 1024, msg, args);
311 int line = xmlSAX2GetLineNumber(state->ctxt);
313 int line = getLineNumber(state->ctxt);
315 state->error_msg +=
"At line: " + long_to_string(line) +
": ";
316 state->error_msg += string(str) + string(
"\n");
323 AISDatabaseParser::aisFatalError(AISParserState *state,
const char *msg, ...)
327 state->state = PARSER_ERROR;
331 vsnprintf(str, 1024, msg, args);
336 int line = xmlSAX2GetLineNumber(state->ctxt);
338 int line = getLineNumber(state->ctxt);
340 state->error_msg +=
"At line: " + long_to_string(line) +
": ";
341 state->error_msg += string(str) + string(
"\n");
348 static xmlSAXHandler aisSAXParser =
355 (getEntitySAXFunc)AISDatabaseParser::aisGetEntity,
362 (startDocumentSAXFunc)AISDatabaseParser::aisStartDocument,
363 (endDocumentSAXFunc)AISDatabaseParser::aisEndDocument,
364 (startElementSAXFunc)AISDatabaseParser::aisStartElement,
365 (endElementSAXFunc)AISDatabaseParser::aisEndElement,
371 (warningSAXFunc)AISDatabaseParser::aisWarning,
372 (errorSAXFunc)AISDatabaseParser::aisError,
373 (fatalErrorSAXFunc)AISDatabaseParser::aisFatalError,
397 xmlParserCtxtPtr ctxt;
398 AISParserState state;
400 ctxt = xmlCreateFileParserCtxt(database.c_str());
407 ctxt->sax = &aisSAXParser;
408 ctxt->userData = &state;
409 ctxt->validate =
true;
411 xmlParseDocument(ctxt);
414 if (!ctxt->wellFormed) {
416 xmlFreeParserCtxt(ctxt);
417 throw AISDatabaseReadFailed(
string(
"\nThe database is not a well formed XML document.\n") + state.error_msg);
422 xmlFreeParserCtxt(ctxt);
426 if (state.state == PARSER_ERROR) {
428 xmlFreeParserCtxt(ctxt);
433 xmlFreeParserCtxt(ctxt);
top level DAP object to house generic methods
Associate a rule with an ancillary resource.