File indexing completed on 2024-04-06 12:11:33
0001 #ifndef Fireworks_Core_FWXMLConfigParser
0002 #define Fireworks_Core_FWXMLConfigParser
0003 #include <istream>
0004 #include <iostream>
0005 #include "Fireworks/Core/interface/SimpleSAXParser.h"
0006
0007 #include "Fireworks/Core/interface/FWConfiguration.h"
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 class FWXMLConfigParser : public SimpleSAXParser {
0033 enum STATES { IN_BEGIN_DOCUMENT, IN_PUSHED_CONFIG, IN_POPPED_CONFIG, IN_BEGIN_STRING, IN_STORED_STRING };
0034
0035 public:
0036 FWXMLConfigParser(std::istream &f) : SimpleSAXParser(f), m_state(IN_BEGIN_DOCUMENT), m_first(nullptr) {}
0037
0038
0039 void pushConfig(Attributes &attributes) {
0040 std::string name;
0041 int version = 0;
0042 for (size_t i = 0, e = attributes.size(); i != e; ++i) {
0043 Attribute &attr = attributes[i];
0044 if (attr.key == "name")
0045 name = attr.value;
0046 else if (attr.key == "version") {
0047 char *endptr;
0048 version = strtol(attr.value.c_str(), &endptr, 10);
0049 if (endptr == attr.value.c_str())
0050 throw ParserError("Version must be an integer.");
0051 } else
0052 throw ParserError("Unexpected attribute " + attr.key);
0053 }
0054 m_configs.push_back(std::make_pair(name, new FWConfiguration(version)));
0055 }
0056
0057
0058
0059
0060 void startElement(const std::string &tag, Attributes &attributes) override {
0061 debug_config_state_machine("start", tag, m_state);
0062 if (m_state == IN_BEGIN_DOCUMENT) {
0063 if (tag != "config")
0064 throw ParserError("Expecting toplevel <config> tag");
0065 pushConfig(attributes);
0066 m_first.reset(m_configs.back().second);
0067 m_state = IN_PUSHED_CONFIG;
0068 } else if (m_state == IN_PUSHED_CONFIG) {
0069 if (tag == "config")
0070 pushConfig(attributes);
0071 else if (tag == "string")
0072 m_state = IN_BEGIN_STRING;
0073 else
0074 throw ParserError("Unexpected element " + tag);
0075 } else if (m_state == IN_POPPED_CONFIG) {
0076 if (tag != "config")
0077 throw ParserError("Unexpected element " + tag);
0078 pushConfig(attributes);
0079 m_state = IN_PUSHED_CONFIG;
0080 } else
0081 throw ParserError("Wrong opening tag found " + tag);
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 void endElement(const std::string &tag) override {
0093 debug_config_state_machine("end", tag, m_state);
0094 if (m_state == IN_PUSHED_CONFIG || m_state == IN_POPPED_CONFIG) {
0095 if (tag != "config")
0096 throw ParserError("Wrong closing tag found " + tag);
0097
0098 FWConfiguration *current = m_configs.back().second;
0099 std::string key = m_configs.back().first;
0100 m_configs.pop_back();
0101 if (!m_configs.empty())
0102 m_configs.back().second->addKeyValue(key, *current);
0103 m_state = IN_POPPED_CONFIG;
0104 } else if (m_state == IN_BEGIN_STRING && tag == "string") {
0105 m_configs.back().second->addValue("");
0106 m_state = IN_PUSHED_CONFIG;
0107 } else if (m_state == IN_STORED_STRING && tag == "string")
0108 m_state = IN_PUSHED_CONFIG;
0109 else
0110 throw ParserError("Wrong closing tag found " + tag);
0111 }
0112
0113
0114
0115
0116
0117
0118 void data(const std::string &data) override {
0119 debug_config_state_machine("data", data, m_state);
0120
0121
0122 if (m_state == IN_BEGIN_STRING) {
0123 m_configs.back().second->addValue(data);
0124 m_state = IN_STORED_STRING;
0125 } else if (strspn(data.c_str(), " \t\n") != data.size())
0126 throw ParserError("Unexpected text " + data);
0127 }
0128
0129
0130
0131
0132 FWConfiguration *config(void) { return m_first.get(); }
0133
0134 void debug_config_state_machine(const char *where, const std::string &tag, int state) {
0135 #ifdef FW_CONFIG_PARSER_DEBUG
0136 static char *debug_states[] = {
0137 "IN_BEGIN_DOCUMENT", "IN_PUSHED_CONFIG", "IN_POPPED_CONFIG", "IN_BEGIN_STRING", "IN_STORED_STRING"};
0138
0139 std::cerr << " " << where << " tag/data " << tag << "in state " << debug_states[state] << std::endl;
0140 #endif
0141 }
0142
0143 private:
0144 std::vector<std::pair<std::string, FWConfiguration *> > m_configs;
0145 enum STATES m_state;
0146 std::unique_ptr<FWConfiguration> m_first;
0147
0148 std::string m_currentConfigName;
0149 };
0150 #endif