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