• 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/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 #define kMinChunkSize   4096
46 
SkDOM()47 SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(nullptr) {}
48 
~SkDOM()49 SkDOM::~SkDOM() {}
50 
getRootNode() const51 const SkDOM::Node* SkDOM::getRootNode() const {
52     return fRoot;
53 }
54 
getFirstChild(const Node * node,const char name[]) const55 const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const {
56     SkASSERT(node);
57     const Node* child = node->fFirstChild;
58 
59     if (name) {
60         for (; child != nullptr; child = child->fNextSibling) {
61             if (!strcmp(name, child->fName)) {
62                 break;
63             }
64         }
65     }
66     return child;
67 }
68 
getNextSibling(const Node * node,const char name[]) const69 const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const {
70     SkASSERT(node);
71     const Node* sibling = node->fNextSibling;
72     if (name) {
73         for (; sibling != nullptr; sibling = sibling->fNextSibling) {
74             if (!strcmp(name, sibling->fName)) {
75                 break;
76             }
77         }
78     }
79     return sibling;
80 }
81 
getType(const Node * node) const82 SkDOM::Type SkDOM::getType(const Node* node) const {
83     SkASSERT(node);
84     return (Type)node->fType;
85 }
86 
getName(const Node * node) const87 const char* SkDOM::getName(const Node* node) const {
88     SkASSERT(node);
89     return node->fName;
90 }
91 
findAttr(const Node * node,const char name[]) const92 const char* SkDOM::findAttr(const Node* node, const char name[]) const {
93     SkASSERT(node);
94     const Attr* attr = node->attrs();
95     const Attr* stop = attr + node->fAttrCount;
96 
97     while (attr < stop) {
98         if (!strcmp(attr->fName, name)) {
99             return attr->fValue;
100         }
101         attr += 1;
102     }
103     return nullptr;
104 }
105 
106 /////////////////////////////////////////////////////////////////////////////////////
107 
getFirstAttr(const Node * node) const108 const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const {
109     return node->fAttrCount ? node->attrs() : nullptr;
110 }
111 
getNextAttr(const Node * node,const Attr * attr) const112 const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const {
113     SkASSERT(node);
114     if (attr == nullptr) {
115         return nullptr;
116     }
117     return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : nullptr;
118 }
119 
getAttrName(const Node * node,const Attr * attr) const120 const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const {
121     SkASSERT(node);
122     SkASSERT(attr);
123     return attr->fName;
124 }
125 
getAttrValue(const Node * node,const Attr * attr) const126 const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const {
127     SkASSERT(node);
128     SkASSERT(attr);
129     return attr->fValue;
130 }
131 
132 /////////////////////////////////////////////////////////////////////////////////////
133 
AttrIter(const SkDOM &,const SkDOM::Node * node)134 SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) {
135     SkASSERT(node);
136     fAttr = node->attrs();
137     fStop = fAttr + node->fAttrCount;
138 }
139 
next(const char ** value)140 const char* SkDOM::AttrIter::next(const char** value) {
141     const char* name = nullptr;
142 
143     if (fAttr < fStop) {
144         name = fAttr->fName;
145         if (value)
146             *value = fAttr->fValue;
147         fAttr += 1;
148     }
149     return name;
150 }
151 
152 //////////////////////////////////////////////////////////////////////////////
153 
154 #include "src/xml/SkDOMParser.h"
155 
build(SkStream & docStream)156 const SkDOM::Node* SkDOM::build(SkStream& docStream) {
157     SkDOMParser parser(&fAlloc);
158     if (!parser.parse(docStream))
159     {
160         SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
161         fRoot = nullptr;
162         fAlloc.reset();
163         return nullptr;
164     }
165     fRoot = parser.getRoot();
166     return fRoot;
167 }
168 
169 ///////////////////////////////////////////////////////////////////////////
170 
walk_dom(const SkDOM & dom,const SkDOM::Node * node,SkXMLParser * parser)171 void SkDOM::walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) {
172     const char* elem = dom.getName(node);
173     if (dom.getType(node) == SkDOM::kText_Type) {
174         SkASSERT(dom.countChildren(node) == 0);
175         parser->text(elem, SkToInt(strlen(elem)));
176         return;
177     }
178 
179     parser->startElement(elem);
180 
181     SkDOM::AttrIter iter(dom, node);
182     const char*     name;
183     const char*     value;
184     while ((name = iter.next(&value)) != nullptr)
185         parser->addAttribute(name, value);
186 
187     node = dom.getFirstChild(node, nullptr);
188     while (node)
189     {
190         walk_dom(dom, node, parser);
191         node = dom.getNextSibling(node, nullptr);
192     }
193 
194     parser->endElement(elem);
195 }
196 
copy(const SkDOM & dom,const SkDOM::Node * node)197 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) {
198     SkDOMParser parser(&fAlloc);
199 
200     walk_dom(dom, node, &parser);
201 
202     fRoot = parser.getRoot();
203     return fRoot;
204 }
205 
beginParsing()206 SkXMLParser* SkDOM::beginParsing() {
207     SkASSERT(!fParser);
208     fParser = std::make_unique<SkDOMParser>(&fAlloc);
209 
210     return fParser.get();
211 }
212 
finishParsing()213 const SkDOM::Node* SkDOM::finishParsing() {
214     SkASSERT(fParser);
215     fRoot = fParser->getRoot();
216     fParser.reset();
217 
218     return fRoot;
219 }
220 
221 //////////////////////////////////////////////////////////////////////////
222 
countChildren(const Node * node,const char elem[]) const223 int SkDOM::countChildren(const Node* node, const char elem[]) const {
224     int count = 0;
225 
226     node = this->getFirstChild(node, elem);
227     while (node) {
228         count += 1;
229         node = this->getNextSibling(node, elem);
230     }
231     return count;
232 }
233 
234 //////////////////////////////////////////////////////////////////////////
235 
236 #include "include/utils/SkParse.h"
237 
findS32(const Node * node,const char name[],int32_t * value) const238 bool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const {
239     const char* vstr = this->findAttr(node, name);
240     return vstr && SkParse::FindS32(vstr, value);
241 }
242 
findScalars(const Node * node,const char name[],SkScalar value[],int count) const243 bool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const {
244     const char* vstr = this->findAttr(node, name);
245     return vstr && SkParse::FindScalars(vstr, value, count);
246 }
247 
findHex(const Node * node,const char name[],uint32_t * value) const248 bool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const {
249     const char* vstr = this->findAttr(node, name);
250     return vstr && SkParse::FindHex(vstr, value);
251 }
252 
findBool(const Node * node,const char name[],bool * value) const253 bool SkDOM::findBool(const Node* node, const char name[], bool* value) const {
254     const char* vstr = this->findAttr(node, name);
255     return vstr && SkParse::FindBool(vstr, value);
256 }
257 
findList(const Node * node,const char name[],const char list[]) const258 int SkDOM::findList(const Node* node, const char name[], const char list[]) const {
259     const char* vstr = this->findAttr(node, name);
260     return vstr ? SkParse::FindList(vstr, list) : -1;
261 }
262 
hasAttr(const Node * node,const char name[],const char value[]) const263 bool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const {
264     const char* vstr = this->findAttr(node, name);
265     return vstr && !strcmp(vstr, value);
266 }
267 
hasS32(const Node * node,const char name[],int32_t target) const268 bool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const {
269     const char* vstr = this->findAttr(node, name);
270     int32_t     value;
271     return vstr && SkParse::FindS32(vstr, &value) && value == target;
272 }
273 
hasScalar(const Node * node,const char name[],SkScalar target) const274 bool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const {
275     const char* vstr = this->findAttr(node, name);
276     SkScalar    value;
277     return vstr && SkParse::FindScalar(vstr, &value) && value == target;
278 }
279 
hasHex(const Node * node,const char name[],uint32_t target) const280 bool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const {
281     const char* vstr = this->findAttr(node, name);
282     uint32_t    value;
283     return vstr && SkParse::FindHex(vstr, &value) && value == target;
284 }
285 
hasBool(const Node * node,const char name[],bool target) const286 bool SkDOM::hasBool(const Node* node, const char name[], bool target) const {
287     const char* vstr = this->findAttr(node, name);
288     bool        value;
289     return vstr && SkParse::FindBool(vstr, &value) && value == target;
290 }
291