24 static const std::map<std::string_view, char> escapes{{
"<",
'<'}, {
">",
'>'}, {
"&",
'&'}, {
""",
'"'}, {
"'",
'\''}};
28 for (
const auto &kv : escapes) {
29 auto position = decodedXml.
find(kv.first);
30 if (position != std::string::npos) {
31 decodedXml.
replace(position, kv.first.length(), 1, kv.second);
46 const xmlChar *localname,
47 const xmlChar *prefix,
50 const xmlChar **namespaces,
53 const xmlChar **attributes)
56 unsigned int index = 0;
57 for (
int indexAttribute = 0; indexAttribute < nb_attributes; ++indexAttribute, index += 5) {
58 std::string attributeName(
reinterpret_cast<const char *
>(attributes[index]));
60 auto valueBegin =
reinterpret_cast<const char *
>(attributes[index + 3]);
61 auto valueEnd =
reinterpret_cast<const char *
>(attributes[index + 4]);
63 valueEnd - valueBegin);
65 attributesMap[attributeName] =
decodeXML(value);
70 std::string_view sPrefix(prefix ==
nullptr ?
"" :
reinterpret_cast<const char *
>(prefix));
72 pParser->OnStartElement(
reinterpret_cast<const char *
>(localname), sPrefix, attributesMap);
77 const xmlChar *localname,
78 const xmlChar *prefix,
96 if (message.
find(
"Namespace") != std::string::npos) {
139 PRECICE_ERROR(
"An unexpected exception occurred during configuration: {}.", e.
what());
151 case (XML_ERR_FATAL):
152 case (XML_ERR_ERROR):
155 case (XML_ERR_WARNING):
170 xmlSAXHandler SAXHandler;
172 memset(&SAXHandler, 0,
sizeof(xmlSAXHandler));
174 SAXHandler.initialized = XML_SAX2_MAGIC;
183 PRECICE_CHECK(ifs,
"XML parser was unable to open configuration file \"{}\"", filePath);
191 xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(&SAXHandler,
static_cast<void *
>(
this),
192 content.
c_str(), content.
size(),
nullptr);
194 xmlParseChunk(ctxt,
nullptr, 0, 1);
195 xmlFreeParserCtxt(ctxt);
206 bool operator<(
const Distance &other)
const
208 return distance < other.distance;
213 bool validPrefix =
std::any_of(DefTags.begin(), DefTags.end(), [prefix](
const auto &tag) { return tag->getNamespace() == prefix; });
216 for (
const auto &tag : DefTags) {
217 if (!validPrefix || (tag->getNamespace() == prefix)) {
218 entries.
insert(tag->getFullName());
229 for (
auto &subtag : SubTags) {
230 std::string expectedName = (subtag->m_Prefix.length() ? subtag->m_Prefix +
":" :
"") + subtag->m_Name;
232 "This configuration contains the tag <solver-interface>, meaning it was created for a preCICE version prior to version 3. "
233 "Are you using the correct version of your simulation case? Has this simulation case been updated to this version of preCICE?");
238 return pTag->_fullName == expectedName;
241 if (tagPosition == DefTags.end()) {
243 auto names = gatherCandidates(DefTags, subtag->m_Prefix);
246 if (!matches.empty() && matches.front().distance < 3) {
247 matches.erase(
std::remove_if(matches.begin(), matches.end(), [](
auto &m) { return m.distance > 2; }), matches.end());
250 PRECICE_ERROR(
"The configuration contains an unknown tag <{}>. Did you mean <{}>?", expectedName, fmt::join(stringMatches,
">,<"));
252 PRECICE_ERROR(
"The configuration contains an unknown tag <{}>. Expected tags are {}.", expectedName, fmt::join(names,
", "));
256 auto pDefSubTag = *tagPosition;
257 pDefSubTag->resetAttributes();
261 "Tag <{}> is not allowed to occur multiple times.", pDefSubTag->_fullName);
262 usedTags.
emplace(pDefSubTag->_fullName);
265 pDefSubTag->_configuredNamespaces[pDefSubTag->_namespace] =
true;
266 pDefSubTag->readAttributes(subtag->m_aAttributes);
267 pDefSubTag->_listener.xmlTagCallback(context, *pDefSubTag);
268 pDefSubTag->_configured =
true;
270 connectTags(context, pDefSubTag->_subtags, subtag->m_aSubTags);
272 pDefSubTag->areAllSubtagsConfigured();
273 pDefSubTag->_listener.xmlEndTagCallback(context, *pDefSubTag);
284 pTag->m_Prefix = prefix;
285 pTag->m_Name = localname;
286 pTag->m_aAttributes = std::move(attributes);
290 pParentTag->m_aSubTags.push_back(pTag);
#define PRECICE_ERROR(...)
#define PRECICE_WARN(...)
#define PRECICE_INFO(...)
#define PRECICE_CHECK(check,...)
T back_inserter(T... args)
This class provides a lightweight logger.
void OnTextSection(const std::string &ch)
Callback for text sections in xml file.
std::vector< std::shared_ptr< CTag > > CTagPtrVec
void OnEndElement()
Callback for End-Tag.
std::shared_ptr< precice::xml::XMLTag > m_pXmlTag
ConfigParser(std::string_view filePath, const ConfigurationContext &context, std::shared_ptr< XMLTag > pXmlTag)
Parser ctor for Callback init.
void OnStartElement(std::string_view localname, std::string_view prefix, CTag::AttributePair attributes)
Callback for Start-Tag.
void connectTags(const ConfigurationContext &context, std::vector< std::shared_ptr< precice::xml::XMLTag > > &DefTags, CTagPtrVec &SubTags)
Connects the actual tags of an xml layer with the predefined tags.
std::string hash() const
returns the hash of the processed XML file
static void MessageProxy(int level, std::string_view mess)
Proxy for error and warning messages from libxml2.
int readXmlFile(std::string const &filePath)
Reads the xml file.
static precice::logging::Logger _log
std::string _hash
the hash of the last processed config
std::string preciceHash(std::string_view s)
creates a portable hash of the given input
std::vector< StringMatch > computeMatches(std::string_view given, const Container &expected)
contains the XML configuration parser.
void OnEndElementNs(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI)
void OnFatalErrorFunc(void *userData, const char *error,...)
void OnStartElementNs(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes)
void OnStructuredErrorFunc(void *userData, const xmlError *error)
void OnCharacters(void *ctx, const xmlChar *ch, int len)
void OnErrorFunc(void *userData, const char *error,...)
std::string decodeXML(std::string_view xml)
Decodes escape sequences of a given xml.
std::map< std::string, std::string > AttributePair
Tightly coupled to the parameters of Participant()