1 //===-- XML.h ---------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_HOST_XML_H
10 #define LLDB_HOST_XML_H
11 
12 #include "lldb/Host/Config.h"
13 
14 #if LLDB_ENABLE_LIBXML2
15 #include <libxml/xmlreader.h>
16 #endif
17 
18 #include <functional>
19 #include <string>
20 #include <vector>
21 
22 #include "llvm/ADT/StringRef.h"
23 
24 #include "lldb/Utility/StreamString.h"
25 #include "lldb/Utility/StructuredData.h"
26 #include "lldb/lldb-private.h"
27 
28 namespace lldb_private {
29 
30 #if LLDB_ENABLE_LIBXML2
31 typedef xmlNodePtr XMLNodeImpl;
32 typedef xmlDocPtr XMLDocumentImpl;
33 #else
34 typedef void *XMLNodeImpl;
35 typedef void *XMLDocumentImpl;
36 #endif
37 
38 class XMLNode;
39 
40 typedef std::vector<std::string> NamePath;
41 typedef std::function<bool(const XMLNode &node)> NodeCallback;
42 typedef std::function<bool(const llvm::StringRef &name,
43                            const llvm::StringRef &value)>
44     AttributeCallback;
45 
46 class XMLNode {
47 public:
48   XMLNode();
49 
50   XMLNode(XMLNodeImpl node);
51 
52   ~XMLNode();
53 
54   explicit operator bool() const { return IsValid(); }
55 
56   void Clear();
57 
58   bool IsValid() const;
59 
60   bool IsElement() const;
61 
62   llvm::StringRef GetName() const;
63 
64   bool GetElementText(std::string &text) const;
65 
66   bool GetElementTextAsUnsigned(uint64_t &value, uint64_t fail_value = 0,
67                                 int base = 0) const;
68 
69   bool GetElementTextAsFloat(double &value, double fail_value = 0.0) const;
70 
71   bool NameIs(const char *name) const;
72 
73   XMLNode GetParent() const;
74 
75   XMLNode GetSibling() const;
76 
77   XMLNode GetChild() const;
78 
79   std::string GetAttributeValue(const char *name,
80                                 const char *fail_value = nullptr) const;
81 
82   bool GetAttributeValueAsUnsigned(const char *name, uint64_t &value,
83                                    uint64_t fail_value = 0, int base = 0) const;
84 
85   XMLNode FindFirstChildElementWithName(const char *name) const;
86 
87   XMLNode GetElementForPath(const NamePath &path);
88 
89   // Iterate through all sibling nodes of any type
90   void ForEachSiblingNode(NodeCallback const &callback) const;
91 
92   // Iterate through only the sibling nodes that are elements
93   void ForEachSiblingElement(NodeCallback const &callback) const;
94 
95   // Iterate through only the sibling nodes that are elements and whose name
96   // matches \a name.
97   void ForEachSiblingElementWithName(const char *name,
98                                      NodeCallback const &callback) const;
99 
100   void ForEachChildNode(NodeCallback const &callback) const;
101 
102   void ForEachChildElement(NodeCallback const &callback) const;
103 
104   void ForEachChildElementWithName(const char *name,
105                                    NodeCallback const &callback) const;
106 
107   void ForEachAttribute(AttributeCallback const &callback) const;
108 
109 protected:
110   XMLNodeImpl m_node = nullptr;
111 };
112 
113 class XMLDocument {
114 public:
115   XMLDocument();
116 
117   ~XMLDocument();
118 
119   explicit operator bool() const { return IsValid(); }
120 
121   bool IsValid() const;
122 
123   void Clear();
124 
125   bool ParseFile(const char *path);
126 
127   bool ParseMemory(const char *xml, size_t xml_length,
128                    const char *url = "untitled.xml");
129 
130   // If \a name is nullptr, just get the root element node, else only return a
131   // value XMLNode if the name of the root element matches \a name.
132   XMLNode GetRootElement(const char *required_name = nullptr);
133 
134   llvm::StringRef GetErrors() const;
135 
136   static void ErrorCallback(void *ctx, const char *format, ...);
137 
138   static bool XMLEnabled();
139 
140 protected:
141   XMLDocumentImpl m_document = nullptr;
142   StreamString m_errors;
143 };
144 
145 class ApplePropertyList {
146 public:
147   ApplePropertyList();
148 
149   ApplePropertyList(const char *path);
150 
151   ~ApplePropertyList();
152 
153   bool ParseFile(const char *path);
154 
155   llvm::StringRef GetErrors() const;
156 
157   explicit operator bool() const { return IsValid(); }
158 
159   bool IsValid() const;
160 
161   XMLNode GetValueNode(const char *key) const;
162 
163   bool GetValueAsString(const char *key, std::string &value) const;
164 
165   StructuredData::ObjectSP GetStructuredData();
166 
167 protected:
168   // Using a node returned from GetValueNode() extract its value as a string
169   // (if possible). Array and dictionary nodes will return false as they have
170   // no string value. Boolean nodes will return true and \a value will be
171   // "true" or "false" as the string value comes from the element name itself.
172   // All other nodes will return the text content of the XMLNode.
173   static bool ExtractStringFromValueNode(const XMLNode &node,
174                                          std::string &value);
175 
176   XMLDocument m_xml_doc;
177   XMLNode m_dict_node;
178 };
179 
180 } // namespace lldb_private
181 
182 #endif // LLDB_HOST_XML_H
183