• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/xml/SkDOM.h"
9 
10 #include <memory>
11 
12 #include "include/core/SkStream.h"
13 #include "include/private/base/SkTo.h"
14 #include "src/xml/SkXMLParser.h"
15 #include "src/xml/SkXMLWriter.h"
16 
parse(const SkDOM & dom,const SkDOMNode * node)17 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) {
18     const char* elemName = dom.getName(node);
19 
20     if (this->startElement(elemName)) {
21         return false;
22     }
23 
24     SkDOM::AttrIter iter(dom, node);
25     const char*     name, *value;
26 
27     while ((name = iter.next(&value)) != nullptr) {
28         if (this->addAttribute(name, value)) {
29             return false;
30         }
31     }
32 
33     if ((node = dom.getFirstChild(node)) != nullptr) {
34         do {
35             if (!this->parse(dom, node)) {
36                 return false;
37             }
38         } while ((node = dom.getNextSibling(node)) != nullptr);
39     }
40     return !this->endElement(elemName);
41 }
42 
43 /////////////////////////////////////////////////////////////////////////
44 
45 
46 /////////////////////////////////////////////////////////////////////////
47 
48 #define kMinChunkSize   4096
49 
SkDOM()50 SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(nullptr) {}
51 
~SkDOM()52 SkDOM::~SkDOM() {}
53 
getRootNode() const54 const SkDOM::Node* SkDOM::getRootNode() const {
55     return fRoot;
56 }
57 
getFirstChild(const Node * node,const char name[]) const58 const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const {
59     SkASSERT(node);
60     const Node* child = node->fFirstChild;
61 
62     if (name) {
63         for (; child != nullptr; child = child->fNextSibling) {
64             if (!strcmp(name, child->fName)) {
65                 break;
66             }
67         }
68     }
69     return child;
70 }
71 
getNextSibling(const Node * node,const char name[]) const72 const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const {
73     SkASSERT(node);
74     const Node* sibling = node->fNextSibling;
75     if (name) {
76         for (; sibling != nullptr; sibling = sibling->fNextSibling) {
77             if (!strcmp(name, sibling->fName)) {
78                 break;
79             }
80         }
81     }
82     return sibling;
83 }
84 
getType(const Node * node) const85 SkDOM::Type SkDOM::getType(const Node* node) const {
86     SkASSERT(node);
87     return (Type)node->fType;
88 }
89 
getName(const Node * node) const90 const char* SkDOM::getName(const Node* node) const {
91     SkASSERT(node);
92     return node->fName;
93 }
94 
findAttr(const Node * node,const char name[]) const95 const char* SkDOM::findAttr(const Node* node, const char name[]) const {
96     SkASSERT(node);
97     const Attr* attr = node->attrs();
98     const Attr* stop = attr + node->fAttrCount;
99 
100     while (attr < stop) {
101         if (!strcmp(attr->fName, name)) {
102             return attr->fValue;
103         }
104         attr += 1;
105     }
106     return nullptr;
107 }
108 
109 /////////////////////////////////////////////////////////////////////////////////////
110 
getFirstAttr(const Node * node) const111 const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const {
112     return node->fAttrCount ? node->attrs() : nullptr;
113 }
114 
getNextAttr(const Node * node,const Attr * attr) const115 const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const {
116     SkASSERT(node);
117     if (attr == nullptr) {
118         return nullptr;
119     }
120     return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : nullptr;
121 }
122 
getAttrName(const Node * node,const Attr * attr) const123 const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const {
124     SkASSERT(node);
125     SkASSERT(attr);
126     return attr->fName;
127 }
128 
getAttrValue(const Node * node,const Attr * attr) const129 const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const {
130     SkASSERT(node);
131     SkASSERT(attr);
132     return attr->fValue;
133 }
134 
135 /////////////////////////////////////////////////////////////////////////////////////
136 
AttrIter(const SkDOM &,const SkDOM::Node * node)137 SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) {
138     SkASSERT(node);
139     fAttr = node->attrs();
140     fStop = fAttr + node->fAttrCount;
141 }
142 
next(const char ** value)143 const char* SkDOM::AttrIter::next(const char** value) {
144     const char* name = nullptr;
145 
146     if (fAttr < fStop) {
147         name = fAttr->fName;
148         if (value)
149             *value = fAttr->fValue;
150         fAttr += 1;
151     }
152     return name;
153 }
154 
155 //////////////////////////////////////////////////////////////////////////////
156 #include "src/xml/SkDOMParser.h"
157 
build(SkStream & docStream)158 const SkDOM::Node* SkDOM::build(SkStream& docStream) {
159     SkDOMParser parser(&fAlloc);
160     if (!parser.parse(docStream))
161     {
162         SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
163         fRoot = nullptr;
164         fAlloc.reset();
165         return nullptr;
166     }
167     fRoot = parser.getRoot();
168     return fRoot;
169 }
170 
171 ///////////////////////////////////////////////////////////////////////////
172 
walk_dom(const SkDOM & dom,const SkDOM::Node * node,SkXMLParser * parser)173 void SkDOM::walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) {
174     const char* elem = dom.getName(node);
175     if (dom.getType(node) == SkDOM::kText_Type) {
176         SkASSERT(dom.countChildren(node) == 0);
177         parser->text(elem, SkToInt(strlen(elem)));
178         return;
179     }
180 
181     parser->startElement(elem);
182 
183     SkDOM::AttrIter iter(dom, node);
184     const char*     name;
185     const char*     value;
186     while ((name = iter.next(&value)) != nullptr)
187         parser->addAttribute(name, value);
188 
189     node = dom.getFirstChild(node, nullptr);
190     while (node)
191     {
192         walk_dom(dom, node, parser);
193         node = dom.getNextSibling(node, nullptr);
194     }
195 
196     parser->endElement(elem);
197 }
198 
copy(const SkDOM & dom,const SkDOM::Node * node)199 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) {
200     SkDOMParser parser(&fAlloc);
201 
202     walk_dom(dom, node, &parser);
203 
204     fRoot = parser.getRoot();
205     return fRoot;
206 }
207 
beginParsing()208 SkXMLParser* SkDOM::beginParsing() {
209     SkASSERT(!fParser);
210     fParser = std::make_unique<SkDOMParser>(&fAlloc);
211 
212     return fParser.get();
213 }
214 
finishParsing()215 const SkDOM::Node* SkDOM::finishParsing() {
216     SkASSERT(fParser);
217     fRoot = fParser->getRoot();
218     fParser.reset();
219 
220     return fRoot;
221 }
222 
223 //////////////////////////////////////////////////////////////////////////
224 
countChildren(const Node * node,const char elem[]) const225 int SkDOM::countChildren(const Node* node, const char elem[]) const {
226     int count = 0;
227 
228     node = this->getFirstChild(node, elem);
229     while (node) {
230         count += 1;
231         node = this->getNextSibling(node, elem);
232     }
233     return count;
234 }
235 
236 //////////////////////////////////////////////////////////////////////////
237 
238 #include "include/utils/SkParse.h"
239 
findS32(const Node * node,const char name[],int32_t * value) const240 bool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const {
241     const char* vstr = this->findAttr(node, name);
242     return vstr && SkParse::FindS32(vstr, value);
243 }
244 
findScalars(const Node * node,const char name[],SkScalar value[],int count) const245 bool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const {
246     const char* vstr = this->findAttr(node, name);
247     return vstr && SkParse::FindScalars(vstr, value, count);
248 }
249 
findHex(const Node * node,const char name[],uint32_t * value) const250 bool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const {
251     const char* vstr = this->findAttr(node, name);
252     return vstr && SkParse::FindHex(vstr, value);
253 }
254 
findBool(const Node * node,const char name[],bool * value) const255 bool SkDOM::findBool(const Node* node, const char name[], bool* value) const {
256     const char* vstr = this->findAttr(node, name);
257     return vstr && SkParse::FindBool(vstr, value);
258 }
259 
findList(const Node * node,const char name[],const char list[]) const260 int SkDOM::findList(const Node* node, const char name[], const char list[]) const {
261     const char* vstr = this->findAttr(node, name);
262     return vstr ? SkParse::FindList(vstr, list) : -1;
263 }
264 
hasAttr(const Node * node,const char name[],const char value[]) const265 bool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const {
266     const char* vstr = this->findAttr(node, name);
267     return vstr && !strcmp(vstr, value);
268 }
269 
hasS32(const Node * node,const char name[],int32_t target) const270 bool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const {
271     const char* vstr = this->findAttr(node, name);
272     int32_t     value;
273     return vstr && SkParse::FindS32(vstr, &value) && value == target;
274 }
275 
hasScalar(const Node * node,const char name[],SkScalar target) const276 bool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const {
277     const char* vstr = this->findAttr(node, name);
278     SkScalar    value;
279     return vstr && SkParse::FindScalar(vstr, &value) && value == target;
280 }
281 
hasHex(const Node * node,const char name[],uint32_t target) const282 bool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const {
283     const char* vstr = this->findAttr(node, name);
284     uint32_t    value;
285     return vstr && SkParse::FindHex(vstr, &value) && value == target;
286 }
287 
hasBool(const Node * node,const char name[],bool target) const288 bool SkDOM::hasBool(const Node* node, const char name[], bool target) const {
289     const char* vstr = this->findAttr(node, name);
290     bool        value;
291     return vstr && SkParse::FindBool(vstr, &value) && value == target;
292 }
293