• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dupstr(SkArenaAlloc * chunk,const char src[],size_t srcLen)10 char* 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 
getRoot() const18 SkDOM::Node* SkDOMParser::getRoot() const {
19     return fRoot;
20 }
21 
flushAttributes()22 void SkDOMParser::flushAttributes() {
23     SkASSERT(fLevel > 0);
24 
25     int attrCount = fAttrs.size();
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.back();
41         SkASSERT(fRoot && parent);
42         node->fNextSibling = parent->fFirstChild;
43         parent->fFirstChild = node;
44     }
45     *fParentStack.append() = node;
46 
47     sk_careful_memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr));
48     fAttrs.reset();
49 }
50 
onStartElement(const char elem[])51 bool SkDOMParser::onStartElement(const char elem[]) {
52     this->startCommon(elem, strlen(elem), SkDOM::kElement_Type);
53     return false;
54 }
55 
onAddAttribute(const char name[],const char value[])56 bool 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 
onEndElement(const char elem[])63 bool SkDOMParser::onEndElement(const char elem[]) {
64     --fLevel;
65     if (fNeedToFlush)
66         flushAttributes();
67     fNeedToFlush = false;
68 
69     SkDOM::Node* parent;
70 
71     parent = fParentStack.back();
72     fParentStack.pop_back();
73 
74     SkDOM::Node* child = parent->fFirstChild;
75     SkDOM::Node* prev = nullptr;
76     while (child) {
77         SkDOM::Node* next = child->fNextSibling;
78         child->fNextSibling = prev;
79         prev = child;
80         child = next;
81     }
82     parent->fFirstChild = prev;
83     return false;
84 }
85 
onText(const char text[],int len)86 bool SkDOMParser::onText(const char text[], int len) {
87     startCommon(text, len, SkDOM::kText_Type);
88     SkDOMParser::onEndElement(fElemName);
89 
90     return false;
91 }
92 
startCommon(const char elem[],size_t elemSize,SkDOM::Type type)93 void SkDOMParser::startCommon(const char elem[], size_t elemSize, SkDOM::Type type) {
94     if (fLevel > 0 && fNeedToFlush) {
95         flushAttributes();
96     }
97     fNeedToFlush = true;
98     fElemName = dupstr(fAlloc, elem, elemSize);
99     fElemType = type;
100     ++fLevel;
101 }
102