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