1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3 * Description: Implementation for Css style parser. 4 * Create: 2023/4/25 5 */ 6 7#include "src/xml/SkDOM.h" 8#include "src/xml/SkDOMParser.h" 9 10char* SkDOMParser::dupstr(SkArenaAlloc* chunk, const char src[], size_t srcLen) { 11 SkASSERT(chunk && src); 12 char* dst = chunk->makeArrayDefault<char>(srcLen + 1); 13 memcpy(dst, src, srcLen); 14 dst[srcLen] = '\0'; 15 return dst; 16} 17 18SkDOM::Node* SkDOMParser::getRoot() const { 19 return fRoot; 20} 21 22void SkDOMParser::flushAttributes() { 23 SkASSERT(fLevel > 0); 24 25 int attrCount = fAttrs.count(); 26 27 SkDOMAttr* attrs = fAlloc->makeArrayDefault<SkDOMAttr>(attrCount); 28 SkDOM::Node* node = fAlloc->make<SkDOM::Node>(); 29 30 node->fName = fElemName; 31 node->fFirstChild = nullptr; 32 node->fAttrCount = SkToU16(attrCount); 33 node->fAttrs = attrs; 34 node->fType = fElemType; 35 36 if (fRoot == nullptr) { 37 node->fNextSibling = nullptr; 38 fRoot = node; 39 } else { // this adds siblings in reverse order. gets corrected in onEndElement() 40 SkDOM::Node* parent = fParentStack.top(); 41 SkASSERT(fRoot && parent); 42 node->fNextSibling = parent->fFirstChild; 43 parent->fFirstChild = node; 44 } 45 *fParentStack.push() = node; 46 47 sk_careful_memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); 48 fAttrs.reset(); 49} 50 51bool SkDOMParser::onStartElement(const char elem[]) { 52 this->startCommon(elem, strlen(elem), SkDOM::kElement_Type); 53 return false; 54} 55 56bool SkDOMParser::onAddAttribute(const char name[], const char value[]) { 57 SkDOM::Attr* attr = fAttrs.append(); 58 attr->fName = dupstr(fAlloc, name, strlen(name)); 59 attr->fValue = dupstr(fAlloc, value, strlen(value)); 60 return false; 61} 62 63bool SkDOMParser::onEndElement(const char elem[]) { 64 --fLevel; 65 if (fNeedToFlush) 66 flushAttributes(); 67 fNeedToFlush = false; 68 69 SkDOM::Node* parent; 70 71 fParentStack.pop(&parent); 72 73 SkDOM::Node* child = parent->fFirstChild; 74 SkDOM::Node* prev = nullptr; 75 while (child) { 76 SkDOM::Node* next = child->fNextSibling; 77 child->fNextSibling = prev; 78 prev = child; 79 child = next; 80 } 81 parent->fFirstChild = prev; 82 return false; 83} 84 85bool SkDOMParser::onText(const char text[], int len) { 86 startCommon(text, len, SkDOM::kText_Type); 87 SkDOMParser::onEndElement(fElemName); 88 89 return false; 90} 91 92void SkDOMParser::startCommon(const char elem[], size_t elemSize, SkDOM::Type type) { 93 if (fLevel > 0 && fNeedToFlush) { 94 flushAttributes(); 95 } 96 fNeedToFlush = true; 97 fElemName = dupstr(fAlloc, elem, elemSize); 98 fElemType = type; 99 ++fLevel; 100} 101