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.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
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 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
onText(const char text[],int len)85 bool SkDOMParser::onText(const char text[], int len) {
86 startCommon(text, len, SkDOM::kText_Type);
87 SkDOMParser::onEndElement(fElemName);
88
89 return false;
90 }
91
startCommon(const char elem[],size_t elemSize,SkDOM::Type type)92 void 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