| 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 |