OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkDOM.h" | 10 #include "SkDOM.h" |
11 #include "SkStream.h" | 11 #include "SkStream.h" |
12 #include "SkXMLWriter.h" | 12 #include "SkXMLWriter.h" |
13 | 13 |
14 ///////////////////////////////////////////////////////////////////////// | 14 ///////////////////////////////////////////////////////////////////////// |
15 | 15 |
16 #include "SkXMLParser.h" | 16 #include "SkXMLParser.h" |
17 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) | 17 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) |
18 { | 18 { |
19 const char* elemName = dom.getName(node); | 19 const char* elemName = dom.getName(node); |
20 | 20 |
21 if (this->startElement(elemName)) | 21 if (this->startElement(elemName)) |
22 return false; | 22 return false; |
23 | 23 |
24 SkDOM::AttrIter iter(dom, node); | 24 SkDOM::AttrIter iter(dom, node); |
25 const char* name, *value; | 25 const char* name, *value; |
26 | 26 |
27 while ((name = iter.next(&value)) != NULL) | 27 while ((name = iter.next(&value)) != nullptr) |
28 if (this->addAttribute(name, value)) | 28 if (this->addAttribute(name, value)) |
29 return false; | 29 return false; |
30 | 30 |
31 if ((node = dom.getFirstChild(node)) != NULL) | 31 if ((node = dom.getFirstChild(node)) != nullptr) |
32 do { | 32 do { |
33 if (!this->parse(dom, node)) | 33 if (!this->parse(dom, node)) |
34 return false; | 34 return false; |
35 } while ((node = dom.getNextSibling(node)) != NULL); | 35 } while ((node = dom.getNextSibling(node)) != nullptr); |
36 | 36 |
37 return !this->endElement(elemName); | 37 return !this->endElement(elemName); |
38 } | 38 } |
39 | 39 |
40 ///////////////////////////////////////////////////////////////////////// | 40 ///////////////////////////////////////////////////////////////////////// |
41 | 41 |
42 struct SkDOMAttr { | 42 struct SkDOMAttr { |
43 const char* fName; | 43 const char* fName; |
44 const char* fValue; | 44 const char* fValue; |
45 }; | 45 }; |
(...skipping 13 matching lines...) Expand all Loading... |
59 SkDOMAttr* attrs() | 59 SkDOMAttr* attrs() |
60 { | 60 { |
61 return (SkDOMAttr*)(this + 1); | 61 return (SkDOMAttr*)(this + 1); |
62 } | 62 } |
63 }; | 63 }; |
64 | 64 |
65 ///////////////////////////////////////////////////////////////////////// | 65 ///////////////////////////////////////////////////////////////////////// |
66 | 66 |
67 #define kMinChunkSize 512 | 67 #define kMinChunkSize 512 |
68 | 68 |
69 SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(NULL) | 69 SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(nullptr) |
70 { | 70 { |
71 } | 71 } |
72 | 72 |
73 SkDOM::~SkDOM() | 73 SkDOM::~SkDOM() |
74 { | 74 { |
75 } | 75 } |
76 | 76 |
77 const SkDOM::Node* SkDOM::getRootNode() const | 77 const SkDOM::Node* SkDOM::getRootNode() const |
78 { | 78 { |
79 return fRoot; | 79 return fRoot; |
80 } | 80 } |
81 | 81 |
82 const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) con
st | 82 const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) con
st |
83 { | 83 { |
84 SkASSERT(node); | 84 SkASSERT(node); |
85 const Node* child = node->fFirstChild; | 85 const Node* child = node->fFirstChild; |
86 | 86 |
87 if (name) | 87 if (name) |
88 { | 88 { |
89 for (; child != NULL; child = child->fNextSibling) | 89 for (; child != nullptr; child = child->fNextSibling) |
90 if (!strcmp(name, child->fName)) | 90 if (!strcmp(name, child->fName)) |
91 break; | 91 break; |
92 } | 92 } |
93 return child; | 93 return child; |
94 } | 94 } |
95 | 95 |
96 const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) co
nst | 96 const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) co
nst |
97 { | 97 { |
98 SkASSERT(node); | 98 SkASSERT(node); |
99 const Node* sibling = node->fNextSibling; | 99 const Node* sibling = node->fNextSibling; |
100 if (name) | 100 if (name) |
101 { | 101 { |
102 for (; sibling != NULL; sibling = sibling->fNextSibling) | 102 for (; sibling != nullptr; sibling = sibling->fNextSibling) |
103 if (!strcmp(name, sibling->fName)) | 103 if (!strcmp(name, sibling->fName)) |
104 break; | 104 break; |
105 } | 105 } |
106 return sibling; | 106 return sibling; |
107 } | 107 } |
108 | 108 |
109 SkDOM::Type SkDOM::getType(const Node* node) const | 109 SkDOM::Type SkDOM::getType(const Node* node) const |
110 { | 110 { |
111 SkASSERT(node); | 111 SkASSERT(node); |
112 return (Type)node->fType; | 112 return (Type)node->fType; |
(...skipping 10 matching lines...) Expand all Loading... |
123 SkASSERT(node); | 123 SkASSERT(node); |
124 const Attr* attr = node->attrs(); | 124 const Attr* attr = node->attrs(); |
125 const Attr* stop = attr + node->fAttrCount; | 125 const Attr* stop = attr + node->fAttrCount; |
126 | 126 |
127 while (attr < stop) | 127 while (attr < stop) |
128 { | 128 { |
129 if (!strcmp(attr->fName, name)) | 129 if (!strcmp(attr->fName, name)) |
130 return attr->fValue; | 130 return attr->fValue; |
131 attr += 1; | 131 attr += 1; |
132 } | 132 } |
133 return NULL; | 133 return nullptr; |
134 } | 134 } |
135 | 135 |
136 ////////////////////////////////////////////////////////////////////////////////
///// | 136 ////////////////////////////////////////////////////////////////////////////////
///// |
137 | 137 |
138 const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const | 138 const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const |
139 { | 139 { |
140 return node->fAttrCount ? node->attrs() : NULL; | 140 return node->fAttrCount ? node->attrs() : nullptr; |
141 } | 141 } |
142 | 142 |
143 const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const | 143 const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const |
144 { | 144 { |
145 SkASSERT(node); | 145 SkASSERT(node); |
146 if (attr == NULL) | 146 if (attr == nullptr) |
147 return NULL; | 147 return nullptr; |
148 return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : NULL; | 148 return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : nullptr; |
149 } | 149 } |
150 | 150 |
151 const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const | 151 const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const |
152 { | 152 { |
153 SkASSERT(node); | 153 SkASSERT(node); |
154 SkASSERT(attr); | 154 SkASSERT(attr); |
155 return attr->fName; | 155 return attr->fName; |
156 } | 156 } |
157 | 157 |
158 const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const | 158 const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const |
159 { | 159 { |
160 SkASSERT(node); | 160 SkASSERT(node); |
161 SkASSERT(attr); | 161 SkASSERT(attr); |
162 return attr->fValue; | 162 return attr->fValue; |
163 } | 163 } |
164 | 164 |
165 ////////////////////////////////////////////////////////////////////////////////
///// | 165 ////////////////////////////////////////////////////////////////////////////////
///// |
166 | 166 |
167 SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) | 167 SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) |
168 { | 168 { |
169 SkASSERT(node); | 169 SkASSERT(node); |
170 fAttr = node->attrs(); | 170 fAttr = node->attrs(); |
171 fStop = fAttr + node->fAttrCount; | 171 fStop = fAttr + node->fAttrCount; |
172 } | 172 } |
173 | 173 |
174 const char* SkDOM::AttrIter::next(const char** value) | 174 const char* SkDOM::AttrIter::next(const char** value) |
175 { | 175 { |
176 const char* name = NULL; | 176 const char* name = nullptr; |
177 | 177 |
178 if (fAttr < fStop) | 178 if (fAttr < fStop) |
179 { | 179 { |
180 name = fAttr->fName; | 180 name = fAttr->fName; |
181 if (value) | 181 if (value) |
182 *value = fAttr->fValue; | 182 *value = fAttr->fValue; |
183 fAttr += 1; | 183 fAttr += 1; |
184 } | 184 } |
185 return name; | 185 return name; |
186 } | 186 } |
(...skipping 10 matching lines...) Expand all Loading... |
197 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp
e); | 197 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp
e); |
198 memcpy(dst, src, len + 1); | 198 memcpy(dst, src, len + 1); |
199 return dst; | 199 return dst; |
200 } | 200 } |
201 | 201 |
202 class SkDOMParser : public SkXMLParser { | 202 class SkDOMParser : public SkXMLParser { |
203 public: | 203 public: |
204 SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) | 204 SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) |
205 { | 205 { |
206 fAlloc->reset(); | 206 fAlloc->reset(); |
207 fRoot = NULL; | 207 fRoot = nullptr; |
208 fLevel = 0; | 208 fLevel = 0; |
209 fNeedToFlush = true; | 209 fNeedToFlush = true; |
210 } | 210 } |
211 SkDOM::Node* getRoot() const { return fRoot; } | 211 SkDOM::Node* getRoot() const { return fRoot; } |
212 SkXMLParserError fParserError; | 212 SkXMLParserError fParserError; |
213 | 213 |
214 protected: | 214 protected: |
215 void flushAttributes() | 215 void flushAttributes() |
216 { | 216 { |
217 SkASSERT(fLevel > 0); | 217 SkASSERT(fLevel > 0); |
218 | 218 |
219 int attrCount = fAttrs.count(); | 219 int attrCount = fAttrs.count(); |
220 | 220 |
221 SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + at
trCount * sizeof(SkDOM::Attr), | 221 SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + at
trCount * sizeof(SkDOM::Attr), |
222 SkChunkAlloc::kThrow_All
ocFailType); | 222 SkChunkAlloc::kThrow_All
ocFailType); |
223 | 223 |
224 node->fName = fElemName; | 224 node->fName = fElemName; |
225 node->fFirstChild = NULL; | 225 node->fFirstChild = nullptr; |
226 node->fAttrCount = SkToU16(attrCount); | 226 node->fAttrCount = SkToU16(attrCount); |
227 node->fType = fElemType; | 227 node->fType = fElemType; |
228 | 228 |
229 if (fRoot == NULL) | 229 if (fRoot == nullptr) |
230 { | 230 { |
231 node->fNextSibling = NULL; | 231 node->fNextSibling = nullptr; |
232 fRoot = node; | 232 fRoot = node; |
233 } | 233 } |
234 else // this adds siblings in reverse order. gets corrected in onEndE
lement() | 234 else // this adds siblings in reverse order. gets corrected in onEndE
lement() |
235 { | 235 { |
236 SkDOM::Node* parent = fParentStack.top(); | 236 SkDOM::Node* parent = fParentStack.top(); |
237 SkASSERT(fRoot && parent); | 237 SkASSERT(fRoot && parent); |
238 node->fNextSibling = parent->fFirstChild; | 238 node->fNextSibling = parent->fFirstChild; |
239 parent->fFirstChild = node; | 239 parent->fFirstChild = node; |
240 } | 240 } |
241 *fParentStack.push() = node; | 241 *fParentStack.push() = node; |
(...skipping 19 matching lines...) Expand all Loading... |
261 --fLevel; | 261 --fLevel; |
262 if (fNeedToFlush) | 262 if (fNeedToFlush) |
263 this->flushAttributes(); | 263 this->flushAttributes(); |
264 fNeedToFlush = false; | 264 fNeedToFlush = false; |
265 | 265 |
266 SkDOM::Node* parent; | 266 SkDOM::Node* parent; |
267 | 267 |
268 fParentStack.pop(&parent); | 268 fParentStack.pop(&parent); |
269 | 269 |
270 SkDOM::Node* child = parent->fFirstChild; | 270 SkDOM::Node* child = parent->fFirstChild; |
271 SkDOM::Node* prev = NULL; | 271 SkDOM::Node* prev = nullptr; |
272 while (child) | 272 while (child) |
273 { | 273 { |
274 SkDOM::Node* next = child->fNextSibling; | 274 SkDOM::Node* next = child->fNextSibling; |
275 child->fNextSibling = prev; | 275 child->fNextSibling = prev; |
276 prev = child; | 276 prev = child; |
277 child = next; | 277 child = next; |
278 } | 278 } |
279 parent->fFirstChild = prev; | 279 parent->fFirstChild = prev; |
280 return false; | 280 return false; |
281 } | 281 } |
(...skipping 28 matching lines...) Expand all Loading... |
310 SkDOM::Type fElemType; | 310 SkDOM::Type fElemType; |
311 int fLevel; | 311 int fLevel; |
312 }; | 312 }; |
313 | 313 |
314 const SkDOM::Node* SkDOM::build(const char doc[], size_t len) | 314 const SkDOM::Node* SkDOM::build(const char doc[], size_t len) |
315 { | 315 { |
316 SkDOMParser parser(&fAlloc); | 316 SkDOMParser parser(&fAlloc); |
317 if (!parser.parse(doc, len)) | 317 if (!parser.parse(doc, len)) |
318 { | 318 { |
319 SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.g
etLineNumber());) | 319 SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.g
etLineNumber());) |
320 fRoot = NULL; | 320 fRoot = nullptr; |
321 fAlloc.reset(); | 321 fAlloc.reset(); |
322 return NULL; | 322 return nullptr; |
323 } | 323 } |
324 fRoot = parser.getRoot(); | 324 fRoot = parser.getRoot(); |
325 return fRoot; | 325 return fRoot; |
326 } | 326 } |
327 | 327 |
328 /////////////////////////////////////////////////////////////////////////// | 328 /////////////////////////////////////////////////////////////////////////// |
329 | 329 |
330 static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par
ser) | 330 static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par
ser) |
331 { | 331 { |
332 const char* elem = dom.getName(node); | 332 const char* elem = dom.getName(node); |
333 if (dom.getType(node) == SkDOM::kText_Type) { | 333 if (dom.getType(node) == SkDOM::kText_Type) { |
334 SkASSERT(dom.countChildren(node) == 0); | 334 SkASSERT(dom.countChildren(node) == 0); |
335 parser->text(elem, SkToInt(strlen(elem))); | 335 parser->text(elem, SkToInt(strlen(elem))); |
336 return; | 336 return; |
337 } | 337 } |
338 | 338 |
339 parser->startElement(elem); | 339 parser->startElement(elem); |
340 | 340 |
341 SkDOM::AttrIter iter(dom, node); | 341 SkDOM::AttrIter iter(dom, node); |
342 const char* name; | 342 const char* name; |
343 const char* value; | 343 const char* value; |
344 while ((name = iter.next(&value)) != NULL) | 344 while ((name = iter.next(&value)) != nullptr) |
345 parser->addAttribute(name, value); | 345 parser->addAttribute(name, value); |
346 | 346 |
347 node = dom.getFirstChild(node, NULL); | 347 node = dom.getFirstChild(node, nullptr); |
348 while (node) | 348 while (node) |
349 { | 349 { |
350 walk_dom(dom, node, parser); | 350 walk_dom(dom, node, parser); |
351 node = dom.getNextSibling(node, NULL); | 351 node = dom.getNextSibling(node, nullptr); |
352 } | 352 } |
353 | 353 |
354 parser->endElement(elem); | 354 parser->endElement(elem); |
355 } | 355 } |
356 | 356 |
357 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) | 357 const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) |
358 { | 358 { |
359 SkDOMParser parser(&fAlloc); | 359 SkDOMParser parser(&fAlloc); |
360 | 360 |
361 walk_dom(dom, node, &parser); | 361 walk_dom(dom, node, &parser); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 bool value; | 461 bool value; |
462 return vstr && SkParse::FindBool(vstr, &value) && value == target; | 462 return vstr && SkParse::FindBool(vstr, &value) && value == target; |
463 } | 463 } |
464 | 464 |
465 ////////////////////////////////////////////////////////////////////////// | 465 ////////////////////////////////////////////////////////////////////////// |
466 | 466 |
467 #ifdef SK_DEBUG | 467 #ifdef SK_DEBUG |
468 | 468 |
469 void SkDOM::dump(const Node* node, int level) const | 469 void SkDOM::dump(const Node* node, int level) const |
470 { | 470 { |
471 if (node == NULL) | 471 if (node == nullptr) |
472 node = this->getRootNode(); | 472 node = this->getRootNode(); |
473 | 473 |
474 SkDebugWStream debugStream; | 474 SkDebugWStream debugStream; |
475 SkXMLStreamWriter xmlWriter(&debugStream); | 475 SkXMLStreamWriter xmlWriter(&debugStream); |
476 xmlWriter.writeDOM(*this, node, false); | 476 xmlWriter.writeDOM(*this, node, false); |
477 } | 477 } |
478 | 478 |
479 void SkDOM::UnitTest() | 479 void SkDOM::UnitTest() |
480 { | 480 { |
481 #ifdef SK_SUPPORT_UNITTEST | 481 #ifdef SK_SUPPORT_UNITTEST |
482 static const char gDoc[] = | 482 static const char gDoc[] = |
483 "<root a='1' b='2'>" | 483 "<root a='1' b='2'>" |
484 "<elem1 c='3' />" | 484 "<elem1 c='3' />" |
485 "<elem2 d='4' />" | 485 "<elem2 d='4' />" |
486 "<elem3 e='5'>" | 486 "<elem3 e='5'>" |
487 "<subelem1/>" | 487 "<subelem1/>" |
488 "<subelem2 f='6' g='7'/>" | 488 "<subelem2 f='6' g='7'/>" |
489 "</elem3>" | 489 "</elem3>" |
490 "<elem4 h='8'/>" | 490 "<elem4 h='8'/>" |
491 "</root>" | 491 "</root>" |
492 ; | 492 ; |
493 | 493 |
494 SkDOM dom; | 494 SkDOM dom; |
495 | 495 |
496 SkASSERT(dom.getRootNode() == NULL); | 496 SkASSERT(dom.getRootNode() == nullptr); |
497 | 497 |
498 const Node* root = dom.build(gDoc, sizeof(gDoc) - 1); | 498 const Node* root = dom.build(gDoc, sizeof(gDoc) - 1); |
499 SkASSERT(root && dom.getRootNode() == root); | 499 SkASSERT(root && dom.getRootNode() == root); |
500 | 500 |
501 const char* v = dom.findAttr(root, "a"); | 501 const char* v = dom.findAttr(root, "a"); |
502 SkASSERT(v && !strcmp(v, "1")); | 502 SkASSERT(v && !strcmp(v, "1")); |
503 v = dom.findAttr(root, "b"); | 503 v = dom.findAttr(root, "b"); |
504 SkASSERT(v && !strcmp(v, "2")); | 504 SkASSERT(v && !strcmp(v, "2")); |
505 v = dom.findAttr(root, "c"); | 505 v = dom.findAttr(root, "c"); |
506 SkASSERT(v == NULL); | 506 SkASSERT(v == nullptr); |
507 | 507 |
508 SkASSERT(dom.getFirstChild(root, "elem1")); | 508 SkASSERT(dom.getFirstChild(root, "elem1")); |
509 SkASSERT(!dom.getFirstChild(root, "subelem1")); | 509 SkASSERT(!dom.getFirstChild(root, "subelem1")); |
510 | 510 |
511 dom.dump(); | 511 dom.dump(); |
512 #endif | 512 #endif |
513 } | 513 } |
514 | 514 |
515 #endif | 515 #endif |
OLD | NEW |