| 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" |
| 12 #include "SkXMLWriter.h" |
| 11 | 13 |
| 12 ///////////////////////////////////////////////////////////////////////// | 14 ///////////////////////////////////////////////////////////////////////// |
| 13 | 15 |
| 14 #include "SkXMLParser.h" | 16 #include "SkXMLParser.h" |
| 15 | |
| 16 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) | 17 bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) |
| 17 { | 18 { |
| 18 const char* elemName = dom.getName(node); | 19 const char* elemName = dom.getName(node); |
| 19 | 20 |
| 20 if (this->startElement(elemName)) | 21 if (this->startElement(elemName)) |
| 21 return false; | 22 return false; |
| 22 | 23 |
| 23 SkDOM::AttrIter iter(dom, node); | 24 SkDOM::AttrIter iter(dom, node); |
| 24 const char* name, *value; | 25 const char* name, *value; |
| 25 | 26 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 static char* dupstr(SkChunkAlloc* chunk, const char src[]) | 193 static char* dupstr(SkChunkAlloc* chunk, const char src[]) |
| 193 { | 194 { |
| 194 SkASSERT(chunk && src); | 195 SkASSERT(chunk && src); |
| 195 size_t len = strlen(src); | 196 size_t len = strlen(src); |
| 196 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp
e); | 197 char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailTyp
e); |
| 197 memcpy(dst, src, len + 1); | 198 memcpy(dst, src, len + 1); |
| 198 return dst; | 199 return dst; |
| 199 } | 200 } |
| 200 | 201 |
| 201 class SkDOMParser : public SkXMLParser { | 202 class SkDOMParser : public SkXMLParser { |
| 202 bool fNeedToFlush; | |
| 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 fRoot = NULL; | 207 fRoot = NULL; |
| 207 fLevel = 0; | 208 fLevel = 0; |
| 208 fNeedToFlush = true; | 209 fNeedToFlush = true; |
| 209 } | 210 } |
| 210 SkDOM::Node* getRoot() const { return fRoot; } | 211 SkDOM::Node* getRoot() const { return fRoot; } |
| 211 SkXMLParserError fParserError; | 212 SkXMLParserError fParserError; |
| 213 |
| 212 protected: | 214 protected: |
| 213 void flushAttributes() | 215 void flushAttributes() |
| 214 { | 216 { |
| 217 SkASSERT(fLevel > 0); |
| 218 |
| 215 int attrCount = fAttrs.count(); | 219 int attrCount = fAttrs.count(); |
| 216 | 220 |
| 217 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), |
| 218 SkChunkAlloc::kThrow_All
ocFailType); | 222 SkChunkAlloc::kThrow_All
ocFailType); |
| 219 | 223 |
| 220 node->fName = fElemName; | 224 node->fName = fElemName; |
| 221 node->fFirstChild = NULL; | 225 node->fFirstChild = NULL; |
| 222 node->fAttrCount = SkToU16(attrCount); | 226 node->fAttrCount = SkToU16(attrCount); |
| 223 node->fType = SkDOM::kElement_Type; | 227 node->fType = fElemType; |
| 224 | 228 |
| 225 if (fRoot == NULL) | 229 if (fRoot == NULL) |
| 226 { | 230 { |
| 227 node->fNextSibling = NULL; | 231 node->fNextSibling = NULL; |
| 228 fRoot = node; | 232 fRoot = node; |
| 229 } | 233 } |
| 230 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() |
| 231 { | 235 { |
| 232 SkDOM::Node* parent = fParentStack.top(); | 236 SkDOM::Node* parent = fParentStack.top(); |
| 233 SkASSERT(fRoot && parent); | 237 SkASSERT(fRoot && parent); |
| 234 node->fNextSibling = parent->fFirstChild; | 238 node->fNextSibling = parent->fFirstChild; |
| 235 parent->fFirstChild = node; | 239 parent->fFirstChild = node; |
| 236 } | 240 } |
| 237 *fParentStack.push() = node; | 241 *fParentStack.push() = node; |
| 238 | 242 |
| 239 memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); | 243 memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); |
| 240 fAttrs.reset(); | 244 fAttrs.reset(); |
| 241 | 245 |
| 242 } | 246 } |
| 243 virtual bool onStartElement(const char elem[]) | 247 |
| 244 { | 248 bool onStartElement(const char elem[]) override { |
| 245 if (fLevel > 0 && fNeedToFlush) | 249 this->startCommon(elem, SkDOM::kElement_Type); |
| 246 this->flushAttributes(); | |
| 247 fNeedToFlush = true; | |
| 248 fElemName = dupstr(fAlloc, elem); | |
| 249 ++fLevel; | |
| 250 return false; | 250 return false; |
| 251 } | 251 } |
| 252 virtual bool onAddAttribute(const char name[], const char value[]) | 252 |
| 253 { | 253 bool onAddAttribute(const char name[], const char value[]) override { |
| 254 SkDOM::Attr* attr = fAttrs.append(); | 254 SkDOM::Attr* attr = fAttrs.append(); |
| 255 attr->fName = dupstr(fAlloc, name); | 255 attr->fName = dupstr(fAlloc, name); |
| 256 attr->fValue = dupstr(fAlloc, value); | 256 attr->fValue = dupstr(fAlloc, value); |
| 257 return false; | 257 return false; |
| 258 } | 258 } |
| 259 virtual bool onEndElement(const char elem[]) | 259 |
| 260 { | 260 bool onEndElement(const char elem[]) override { |
| 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 = NULL; |
| 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 } |
| 282 |
| 283 bool onText(const char text[], int len) override { |
| 284 SkString str(text, len); |
| 285 this->startCommon(str.c_str(), SkDOM::kText_Type); |
| 286 this->SkDOMParser::onEndElement(str.c_str()); |
| 287 |
| 288 return false; |
| 289 } |
| 290 |
| 282 private: | 291 private: |
| 292 void startCommon(const char elem[], SkDOM::Type type) { |
| 293 if (fLevel > 0 && fNeedToFlush) |
| 294 this->flushAttributes(); |
| 295 |
| 296 fNeedToFlush = true; |
| 297 fElemName = dupstr(fAlloc, elem); |
| 298 fElemType = type; |
| 299 ++fLevel; |
| 300 } |
| 301 |
| 283 SkTDArray<SkDOM::Node*> fParentStack; | 302 SkTDArray<SkDOM::Node*> fParentStack; |
| 284 SkChunkAlloc* fAlloc; | 303 SkChunkAlloc* fAlloc; |
| 285 SkDOM::Node* fRoot; | 304 SkDOM::Node* fRoot; |
| 305 bool fNeedToFlush; |
| 286 | 306 |
| 287 // state needed for flushAttributes() | 307 // state needed for flushAttributes() |
| 288 SkTDArray<SkDOM::Attr> fAttrs; | 308 SkTDArray<SkDOM::Attr> fAttrs; |
| 289 char* fElemName; | 309 char* fElemName; |
| 310 SkDOM::Type fElemType; |
| 290 int fLevel; | 311 int fLevel; |
| 291 }; | 312 }; |
| 292 | 313 |
| 293 const SkDOM::Node* SkDOM::build(const char doc[], size_t len) | 314 const SkDOM::Node* SkDOM::build(const char doc[], size_t len) |
| 294 { | 315 { |
| 295 fAlloc.reset(); | |
| 296 SkDOMParser parser(&fAlloc); | 316 SkDOMParser parser(&fAlloc); |
| 297 if (!parser.parse(doc, len)) | 317 if (!parser.parse(doc, len)) |
| 298 { | 318 { |
| 299 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());) |
| 300 fRoot = NULL; | 320 fRoot = NULL; |
| 301 fAlloc.reset(); | 321 fAlloc.reset(); |
| 302 return NULL; | 322 return NULL; |
| 303 } | 323 } |
| 304 fRoot = parser.getRoot(); | 324 fRoot = parser.getRoot(); |
| 305 return fRoot; | 325 return fRoot; |
| 306 } | 326 } |
| 307 | 327 |
| 308 /////////////////////////////////////////////////////////////////////////// | 328 /////////////////////////////////////////////////////////////////////////// |
| 309 | 329 |
| 310 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) |
| 311 { | 331 { |
| 312 const char* elem = dom.getName(node); | 332 const char* elem = dom.getName(node); |
| 333 if (dom.getType(node) == SkDOM::kText_Type) { |
| 334 SkASSERT(dom.countChildren(node) == 0); |
| 335 parser->text(elem, SkToInt(strlen(elem))); |
| 336 return; |
| 337 } |
| 313 | 338 |
| 314 parser->startElement(elem); | 339 parser->startElement(elem); |
| 315 | 340 |
| 316 SkDOM::AttrIter iter(dom, node); | 341 SkDOM::AttrIter iter(dom, node); |
| 317 const char* name; | 342 const char* name; |
| 318 const char* value; | 343 const char* value; |
| 319 while ((name = iter.next(&value)) != NULL) | 344 while ((name = iter.next(&value)) != NULL) |
| 320 parser->addAttribute(name, value); | 345 parser->addAttribute(name, value); |
| 321 | 346 |
| 322 node = dom.getFirstChild(node, NULL); | 347 node = dom.getFirstChild(node, NULL); |
| 323 while (node) | 348 while (node) |
| 324 { | 349 { |
| 325 walk_dom(dom, node, parser); | 350 walk_dom(dom, node, parser); |
| 326 node = dom.getNextSibling(node, NULL); | 351 node = dom.getNextSibling(node, NULL); |
| 327 } | 352 } |
| 328 | 353 |
| 329 parser->endElement(elem); | 354 parser->endElement(elem); |
| 330 } | 355 } |
| 331 | 356 |
| 332 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) |
| 333 { | 358 { |
| 334 fAlloc.reset(); | |
| 335 SkDOMParser parser(&fAlloc); | 359 SkDOMParser parser(&fAlloc); |
| 336 | 360 |
| 337 walk_dom(dom, node, &parser); | 361 walk_dom(dom, node, &parser); |
| 338 | 362 |
| 339 fRoot = parser.getRoot(); | 363 fRoot = parser.getRoot(); |
| 340 return fRoot; | 364 return fRoot; |
| 341 } | 365 } |
| 342 | 366 |
| 367 SkXMLParser* SkDOM::beginParsing() { |
| 368 SkASSERT(!fParser); |
| 369 fParser.reset(SkNEW_ARGS(SkDOMParser, (&fAlloc))); |
| 370 |
| 371 return fParser.get(); |
| 372 } |
| 373 |
| 374 const SkDOM::Node* SkDOM::finishParsing() { |
| 375 SkASSERT(fParser); |
| 376 fRoot = fParser->getRoot(); |
| 377 fParser.free(); |
| 378 |
| 379 return fRoot; |
| 380 } |
| 381 |
| 343 ////////////////////////////////////////////////////////////////////////// | 382 ////////////////////////////////////////////////////////////////////////// |
| 344 | 383 |
| 345 int SkDOM::countChildren(const Node* node, const char elem[]) const | 384 int SkDOM::countChildren(const Node* node, const char elem[]) const |
| 346 { | 385 { |
| 347 int count = 0; | 386 int count = 0; |
| 348 | 387 |
| 349 node = this->getFirstChild(node, elem); | 388 node = this->getFirstChild(node, elem); |
| 350 while (node) | 389 while (node) |
| 351 { | 390 { |
| 352 count += 1; | 391 count += 1; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 { | 459 { |
| 421 const char* vstr = this->findAttr(node, name); | 460 const char* vstr = this->findAttr(node, name); |
| 422 bool value; | 461 bool value; |
| 423 return vstr && SkParse::FindBool(vstr, &value) && value == target; | 462 return vstr && SkParse::FindBool(vstr, &value) && value == target; |
| 424 } | 463 } |
| 425 | 464 |
| 426 ////////////////////////////////////////////////////////////////////////// | 465 ////////////////////////////////////////////////////////////////////////// |
| 427 | 466 |
| 428 #ifdef SK_DEBUG | 467 #ifdef SK_DEBUG |
| 429 | 468 |
| 430 static void tab(int level) | |
| 431 { | |
| 432 while (--level >= 0) | |
| 433 SkDebugf("\t"); | |
| 434 } | |
| 435 | |
| 436 void SkDOM::dump(const Node* node, int level) const | 469 void SkDOM::dump(const Node* node, int level) const |
| 437 { | 470 { |
| 438 if (node == NULL) | 471 if (node == NULL) |
| 439 node = this->getRootNode(); | 472 node = this->getRootNode(); |
| 440 if (node) | |
| 441 { | |
| 442 tab(level); | |
| 443 SkDebugf("<%s", this->getName(node)); | |
| 444 | 473 |
| 445 const Attr* attr = node->attrs(); | 474 SkDebugWStream debugStream; |
| 446 const Attr* stop = attr + node->fAttrCount; | 475 SkXMLStreamWriter xmlWriter(&debugStream); |
| 447 for (; attr < stop; attr++) | 476 xmlWriter.writeDOM(*this, node, false); |
| 448 SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue); | |
| 449 | |
| 450 const Node* child = this->getFirstChild(node); | |
| 451 if (child) | |
| 452 { | |
| 453 SkDebugf(">\n"); | |
| 454 while (child) | |
| 455 { | |
| 456 this->dump(child, level+1); | |
| 457 child = this->getNextSibling(child); | |
| 458 } | |
| 459 tab(level); | |
| 460 SkDebugf("</%s>\n", node->fName); | |
| 461 } | |
| 462 else | |
| 463 SkDebugf("/>\n"); | |
| 464 } | |
| 465 } | 477 } |
| 466 | 478 |
| 467 void SkDOM::UnitTest() | 479 void SkDOM::UnitTest() |
| 468 { | 480 { |
| 469 #ifdef SK_SUPPORT_UNITTEST | 481 #ifdef SK_SUPPORT_UNITTEST |
| 470 static const char gDoc[] = | 482 static const char gDoc[] = |
| 471 "<root a='1' b='2'>" | 483 "<root a='1' b='2'>" |
| 472 "<elem1 c='3' />" | 484 "<elem1 c='3' />" |
| 473 "<elem2 d='4' />" | 485 "<elem2 d='4' />" |
| 474 "<elem3 e='5'>" | 486 "<elem3 e='5'>" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 494 SkASSERT(v == NULL); | 506 SkASSERT(v == NULL); |
| 495 | 507 |
| 496 SkASSERT(dom.getFirstChild(root, "elem1")); | 508 SkASSERT(dom.getFirstChild(root, "elem1")); |
| 497 SkASSERT(!dom.getFirstChild(root, "subelem1")); | 509 SkASSERT(!dom.getFirstChild(root, "subelem1")); |
| 498 | 510 |
| 499 dom.dump(); | 511 dom.dump(); |
| 500 #endif | 512 #endif |
| 501 } | 513 } |
| 502 | 514 |
| 503 #endif | 515 #endif |
| OLD | NEW |