Files
clang-p2996/lldb/source/Host/common/XML.cpp
Raphael Isemann 808142876c [lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).

This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).

Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere

Reviewed By: JDevlieghere

Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 08:52:55 +01:00

543 lines
14 KiB
C++

//===-- XML.cpp -----------------------------------------------------------===//
//
// 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;
}