diff options
author | 2020-08-03 14:33:06 +0000 | |
---|---|---|
committer | 2020-08-03 14:33:06 +0000 | |
commit | 061da546b983eb767bad15e67af1174fb0bcf31c (patch) | |
tree | 83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/source/Host/common/XML.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/source/Host/common/XML.cpp')
-rw-r--r-- | gnu/llvm/lldb/source/Host/common/XML.cpp | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/source/Host/common/XML.cpp b/gnu/llvm/lldb/source/Host/common/XML.cpp new file mode 100644 index 00000000000..28d1f5a8eaf --- /dev/null +++ b/gnu/llvm/lldb/source/Host/common/XML.cpp @@ -0,0 +1,542 @@ +//===-- XML.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <stdlib.h> /* atof */ + +#include "lldb/Host/Config.h" +#include "lldb/Host/StringConvert.h" +#include "lldb/Host/XML.h" + +using namespace lldb; +using namespace lldb_private; + +#pragma mark-- XMLDocument + +XMLDocument::XMLDocument() : m_document(nullptr) {} + +XMLDocument::~XMLDocument() { Clear(); } + +void XMLDocument::Clear() { +#if LLDB_ENABLE_LIBXML2 + if (m_document) { + xmlDocPtr doc = m_document; + m_document = nullptr; + xmlFreeDoc(doc); + } +#endif +} + +bool XMLDocument::IsValid() const { return m_document != nullptr; } + +void XMLDocument::ErrorCallback(void *ctx, const char *format, ...) { + XMLDocument *document = (XMLDocument *)ctx; + va_list args; + va_start(args, format); + document->m_errors.PrintfVarArg(format, args); + document->m_errors.EOL(); + va_end(args); +} + +bool XMLDocument::ParseFile(const char *path) { +#if LLDB_ENABLE_LIBXML2 + Clear(); + xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback); + m_document = xmlParseFile(path); + xmlSetGenericErrorFunc(nullptr, nullptr); +#endif + return IsValid(); +} + +bool XMLDocument::ParseMemory(const char *xml, size_t xml_length, + const char *url) { +#if LLDB_ENABLE_LIBXML2 + Clear(); + xmlSetGenericErrorFunc((void *)this, XMLDocument::ErrorCallback); + m_document = xmlReadMemory(xml, (int)xml_length, url, nullptr, 0); + xmlSetGenericErrorFunc(nullptr, nullptr); +#endif + return IsValid(); +} + +XMLNode XMLDocument::GetRootElement(const char *required_name) { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + XMLNode root_node(xmlDocGetRootElement(m_document)); + if (required_name) { + llvm::StringRef actual_name = root_node.GetName(); + if (actual_name == required_name) + return root_node; + } else { + return root_node; + } + } +#endif + return XMLNode(); +} + +llvm::StringRef XMLDocument::GetErrors() const { return m_errors.GetString(); } + +bool XMLDocument::XMLEnabled() { +#if LLDB_ENABLE_LIBXML2 + return true; +#else + return false; +#endif +} + +#pragma mark-- XMLNode + +XMLNode::XMLNode() : m_node(nullptr) {} + +XMLNode::XMLNode(XMLNodeImpl node) : m_node(node) {} + +XMLNode::~XMLNode() {} + +void XMLNode::Clear() { m_node = nullptr; } + +XMLNode XMLNode::GetParent() const { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) + return XMLNode(m_node->parent); + else + return XMLNode(); +#else + return XMLNode(); +#endif +} + +XMLNode XMLNode::GetSibling() const { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) + return XMLNode(m_node->next); + else + return XMLNode(); +#else + return XMLNode(); +#endif +} + +XMLNode XMLNode::GetChild() const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) + return XMLNode(m_node->children); + else + return XMLNode(); +#else + return XMLNode(); +#endif +} + +llvm::StringRef XMLNode::GetAttributeValue(const char *name, + const char *fail_value) const { + const char *attr_value = nullptr; +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) + attr_value = (const char *)xmlGetProp(m_node, (const xmlChar *)name); + else + attr_value = fail_value; +#else + attr_value = fail_value; +#endif + if (attr_value) + return llvm::StringRef(attr_value); + else + return llvm::StringRef(); +} + +bool XMLNode::GetAttributeValueAsUnsigned(const char *name, uint64_t &value, + uint64_t fail_value, int base) const { +#if LLDB_ENABLE_LIBXML2 + llvm::StringRef str_value = GetAttributeValue(name, ""); +#else + llvm::StringRef str_value; +#endif + bool success = false; + value = StringConvert::ToUInt64(str_value.data(), fail_value, base, &success); + return success; +} + +void XMLNode::ForEachChildNode(NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) + GetChild().ForEachSiblingNode(callback); +#endif +} + +void XMLNode::ForEachChildElement(NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + XMLNode child = GetChild(); + if (child) + child.ForEachSiblingElement(callback); +#endif +} + +void XMLNode::ForEachChildElementWithName(const char *name, + NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + XMLNode child = GetChild(); + if (child) + child.ForEachSiblingElementWithName(name, callback); +#endif +} + +void XMLNode::ForEachAttribute(AttributeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + for (xmlAttrPtr attr = m_node->properties; attr != nullptr; + attr = attr->next) { + // check if name matches + if (attr->name) { + // check child is a text node + xmlNodePtr child = attr->children; + if (child->type == XML_TEXT_NODE) { + llvm::StringRef attr_value; + if (child->content) + attr_value = llvm::StringRef((const char *)child->content); + if (!callback(llvm::StringRef((const char *)attr->name), attr_value)) + return; + } + } + } + } +#endif +} + +void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + if (!callback(XMLNode(node))) + return; + } + } +#endif +} + +void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + // we are looking for element nodes only + if (node->type != XML_ELEMENT_NODE) + continue; + + if (!callback(XMLNode(node))) + return; + } + } +#endif +} + +void XMLNode::ForEachSiblingElementWithName( + const char *name, NodeCallback const &callback) const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + // iterate through all siblings + for (xmlNodePtr node = m_node; node; node = node->next) { + // we are looking for element nodes only + if (node->type != XML_ELEMENT_NODE) + continue; + + // If name is nullptr, we take all nodes of type "t", else just the ones + // whose name matches + if (name) { + if (strcmp((const char *)node->name, name) != 0) + continue; // Name mismatch, ignore this one + } else { + if (node->name) + continue; // nullptr name specified and this element has a name, + // ignore this one + } + + if (!callback(XMLNode(node))) + return; + } + } +#endif +} + +llvm::StringRef XMLNode::GetName() const { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + if (m_node->name) + return llvm::StringRef((const char *)m_node->name); + } +#endif + return llvm::StringRef(); +} + +bool XMLNode::GetElementText(std::string &text) const { + text.clear(); +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + bool success = false; + if (m_node->type == XML_ELEMENT_NODE) { + // check child is a text node + for (xmlNodePtr node = m_node->children; node != nullptr; + node = node->next) { + if (node->type == XML_TEXT_NODE) { + text.append((const char *)node->content); + success = true; + } + } + } + return success; + } +#endif + return false; +} + +bool XMLNode::GetElementTextAsUnsigned(uint64_t &value, uint64_t fail_value, + int base) const { + bool success = false; +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + std::string text; + if (GetElementText(text)) + value = StringConvert::ToUInt64(text.c_str(), fail_value, base, &success); + } +#endif + if (!success) + value = fail_value; + return success; +} + +bool XMLNode::GetElementTextAsFloat(double &value, double fail_value) const { + bool success = false; +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + std::string text; + if (GetElementText(text)) { + value = atof(text.c_str()); + success = true; + } + } +#endif + if (!success) + value = fail_value; + return success; +} + +bool XMLNode::NameIs(const char *name) const { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + // In case we are looking for a nullptr name or an exact pointer match + if (m_node->name == (const xmlChar *)name) + return true; + if (m_node->name) + return strcmp((const char *)m_node->name, name) == 0; + } +#endif + return false; +} + +XMLNode XMLNode::FindFirstChildElementWithName(const char *name) const { + XMLNode result_node; + +#if LLDB_ENABLE_LIBXML2 + ForEachChildElementWithName( + name, [&result_node](const XMLNode &node) -> bool { + result_node = node; + // Stop iterating, we found the node we wanted + return false; + }); +#endif + + return result_node; +} + +bool XMLNode::IsValid() const { return m_node != nullptr; } + +bool XMLNode::IsElement() const { +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) + return m_node->type == XML_ELEMENT_NODE; +#endif + return false; +} + +XMLNode XMLNode::GetElementForPath(const NamePath &path) { +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + if (path.empty()) + return *this; + else { + XMLNode node = FindFirstChildElementWithName(path[0].c_str()); + const size_t n = path.size(); + for (size_t i = 1; node && i < n; ++i) + node = node.FindFirstChildElementWithName(path[i].c_str()); + return node; + } + } +#endif + + return XMLNode(); +} + +#pragma mark-- ApplePropertyList + +ApplePropertyList::ApplePropertyList() : m_xml_doc(), m_dict_node() {} + +ApplePropertyList::ApplePropertyList(const char *path) + : m_xml_doc(), m_dict_node() { + ParseFile(path); +} + +ApplePropertyList::~ApplePropertyList() {} + +llvm::StringRef ApplePropertyList::GetErrors() const { + return m_xml_doc.GetErrors(); +} + +bool ApplePropertyList::ParseFile(const char *path) { + if (m_xml_doc.ParseFile(path)) { + XMLNode plist = m_xml_doc.GetRootElement("plist"); + if (plist) { + plist.ForEachChildElementWithName("dict", + [this](const XMLNode &dict) -> bool { + this->m_dict_node = dict; + return false; // Stop iterating + }); + return (bool)m_dict_node; + } + } + return false; +} + +bool ApplePropertyList::IsValid() const { return (bool)m_dict_node; } + +bool ApplePropertyList::GetValueAsString(const char *key, + std::string &value) const { + XMLNode value_node = GetValueNode(key); + if (value_node) + return ApplePropertyList::ExtractStringFromValueNode(value_node, value); + return false; +} + +XMLNode ApplePropertyList::GetValueNode(const char *key) const { + XMLNode value_node; +#if LLDB_ENABLE_LIBXML2 + + if (IsValid()) { + m_dict_node.ForEachChildElementWithName( + "key", [key, &value_node](const XMLNode &key_node) -> bool { + std::string key_name; + if (key_node.GetElementText(key_name)) { + if (key_name == key) { + value_node = key_node.GetSibling(); + while (value_node && !value_node.IsElement()) + value_node = value_node.GetSibling(); + return false; // Stop iterating + } + } + return true; // Keep iterating + }); + } +#endif + return value_node; +} + +bool ApplePropertyList::ExtractStringFromValueNode(const XMLNode &node, + std::string &value) { + value.clear(); +#if LLDB_ENABLE_LIBXML2 + if (node.IsValid()) { + llvm::StringRef element_name = node.GetName(); + if (element_name == "true" || element_name == "false") { + // The text value _is_ the element name itself... + value = element_name.str(); + return true; + } else if (element_name == "dict" || element_name == "array") + return false; // dictionaries and arrays have no text value, so we fail + else + return node.GetElementText(value); + } +#endif + return false; +} + +#if LLDB_ENABLE_LIBXML2 + +namespace { + +StructuredData::ObjectSP CreatePlistValue(XMLNode node) { + llvm::StringRef element_name = node.GetName(); + if (element_name == "array") { + std::shared_ptr<StructuredData::Array> array_sp( + new StructuredData::Array()); + node.ForEachChildElement([&array_sp](const XMLNode &node) -> bool { + array_sp->AddItem(CreatePlistValue(node)); + return true; // Keep iterating through all child elements of the array + }); + return array_sp; + } else if (element_name == "dict") { + XMLNode key_node; + std::shared_ptr<StructuredData::Dictionary> dict_sp( + new StructuredData::Dictionary()); + node.ForEachChildElement( + [&key_node, &dict_sp](const XMLNode &node) -> bool { + if (node.NameIs("key")) { + // This is a "key" element node + key_node = node; + } else { + // This is a value node + if (key_node) { + std::string key_name; + key_node.GetElementText(key_name); + dict_sp->AddItem(key_name, CreatePlistValue(node)); + key_node.Clear(); + } + } + return true; // Keep iterating through all child elements of the + // dictionary + }); + return dict_sp; + } else if (element_name == "real") { + double value = 0.0; + node.GetElementTextAsFloat(value); + return StructuredData::ObjectSP(new StructuredData::Float(value)); + } else if (element_name == "integer") { + uint64_t value = 0; + node.GetElementTextAsUnsigned(value, 0, 0); + return StructuredData::ObjectSP(new StructuredData::Integer(value)); + } else if ((element_name == "string") || (element_name == "data") || + (element_name == "date")) { + std::string text; + node.GetElementText(text); + return StructuredData::ObjectSP( + new StructuredData::String(std::move(text))); + } else if (element_name == "true") { + return StructuredData::ObjectSP(new StructuredData::Boolean(true)); + } else if (element_name == "false") { + return StructuredData::ObjectSP(new StructuredData::Boolean(false)); + } + return StructuredData::ObjectSP(new StructuredData::Null()); +} +} +#endif + +StructuredData::ObjectSP ApplePropertyList::GetStructuredData() { + StructuredData::ObjectSP root_sp; +#if LLDB_ENABLE_LIBXML2 + if (IsValid()) { + return CreatePlistValue(m_dict_node); + } +#endif + return root_sp; +} |