1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef OHOS_ROSEN_XML_CONFIG_BASE_H
17#define OHOS_ROSEN_XML_CONFIG_BASE_H
18
19#include <map>
20#include <mutex>
21#include <string>
22#include <vector>
23
24namespace OHOS {
25namespace Rosen {
26class XmlConfigBase {
27public:
28    enum class ValueType {
29        UNDIFINED,
30        MAP,
31        BOOL,
32        STRING,
33        STRINGS,
34        INTS,
35        FLOATS,
36        POSITIVE_FLOATS,
37    };
38    struct ConfigItem {
39        std::map<std::string, ConfigItem>* property_ = nullptr;
40        ValueType type_ = ValueType::UNDIFINED;
41        union {
42            std::map<std::string, ConfigItem>* mapValue_ = nullptr;
43            bool boolValue_;
44            std::string stringValue_;
45            std::vector<int>* intsValue_;
46            std::vector<float>* floatsValue_;
47            std::vector<std::string>* stringsValue_;
48        };
49        ConfigItem() {}
50        ~ConfigItem()
51        {
52            Destroy();
53        };
54        void Destroy()
55        {
56            ClearValue();
57            if (property_) {
58                delete property_;
59                property_ = nullptr;
60            }
61        }
62        void ClearValue()
63        {
64            switch (type_) {
65                case ValueType::MAP:
66                    delete mapValue_;
67                    mapValue_ = nullptr;
68                    break;
69                case ValueType::STRING:
70                    stringValue_.~basic_string();
71                    break;
72                case ValueType::INTS:
73                    delete intsValue_;
74                    intsValue_ = nullptr;
75                    break;
76                case ValueType::FLOATS:
77                    delete floatsValue_;
78                    floatsValue_ = nullptr;
79                    break;
80                case ValueType::STRINGS:
81                    delete stringsValue_;
82                    stringsValue_ = nullptr;
83                    break;
84                default:
85                    break;
86            }
87        }
88        ConfigItem(const ConfigItem& value)
89        {
90            *this = value;
91        }
92        ConfigItem& operator=(const ConfigItem& value)
93        {
94            Destroy();
95            switch (value.type_) {
96                case ValueType::MAP:
97                    mapValue_ = new std::map<std::string, ConfigItem>(*value.mapValue_);
98                    break;
99                case ValueType::BOOL:
100                    boolValue_ = value.boolValue_;
101                    break;
102                case ValueType::STRING:
103                    new(&stringValue_)std::string(value.stringValue_);
104                    break;
105                case ValueType::INTS:
106                    intsValue_ = new std::vector<int>(*value.intsValue_);
107                    break;
108                case ValueType::FLOATS:
109                    floatsValue_ = new std::vector<float>(*value.floatsValue_);
110                    break;
111                case ValueType::STRINGS:
112                    stringsValue_ = new std::vector<std::string>(*value.stringsValue_);
113                    break;
114                default:
115                    break;
116            }
117            type_ = value.type_;
118            if (value.property_) {
119                property_ = new std::map<std::string, ConfigItem>(*value.property_);
120            }
121            return *this;
122        }
123        ConfigItem(ConfigItem&& value) noexcept
124        {
125            *this = std::move(value);
126        }
127        ConfigItem& operator=(ConfigItem&& value) noexcept
128        {
129            Destroy();
130            switch (value.type_) {
131                case ValueType::MAP:
132                    mapValue_ = value.mapValue_;
133                    value.mapValue_ = nullptr;
134                    break;
135                case ValueType::BOOL:
136                    boolValue_ = value.boolValue_;
137                    break;
138                case ValueType::STRING:
139                    new(&stringValue_)std::string(std::move(value.stringValue_));
140                    break;
141                case ValueType::INTS:
142                    intsValue_ = value.intsValue_;
143                    value.intsValue_ = nullptr;
144                    break;
145                case ValueType::FLOATS:
146                    floatsValue_ = value.floatsValue_;
147                    value.floatsValue_ = nullptr;
148                    break;
149                case ValueType::STRINGS:
150                    stringsValue_ = value.stringsValue_;
151                    value.stringsValue_ = nullptr;
152                    break;
153                default:
154                    break;
155            }
156            type_ = value.type_;
157            property_ = value.property_;
158            value.type_ = ValueType::UNDIFINED;
159            value.property_ = nullptr;
160            return *this;
161        }
162        void SetProperty(const std::map<std::string, ConfigItem>& prop)
163        {
164            if (property_) {
165                delete property_;
166            }
167            property_ = new std::map<std::string, ConfigItem>(prop);
168        }
169        // set map value
170        void SetValue(const std::map<std::string, ConfigItem>& value)
171        {
172            ClearValue();
173            type_ = ValueType::MAP;
174            mapValue_ = new std::map<std::string, ConfigItem>(value);
175        }
176        // set bool value
177        void SetValue(bool value)
178        {
179            ClearValue();
180            type_ = ValueType::BOOL;
181            boolValue_ = value;
182        }
183        // set string value
184        void SetValue(const std::string& value)
185        {
186            ClearValue();
187            type_ = ValueType::STRING;
188            new(&stringValue_)std::string(value);
189        }
190        // set ints value
191        void SetValue(const std::vector<int>& value)
192        {
193            ClearValue();
194            type_ = ValueType::INTS;
195            intsValue_ = new std::vector<int>(value);
196        }
197        // set floats value
198        void SetValue(const std::vector<float>& value)
199        {
200            ClearValue();
201            type_ = ValueType::FLOATS;
202            floatsValue_ = new std::vector<float>(value);
203        }
204        // set strings value
205        void SetValue(const std::vector<std::string>& value)
206        {
207            ClearValue();
208            type_ = ValueType::STRINGS;
209            stringsValue_ = new std::vector<std::string>(value);
210        }
211        bool IsInts() const
212        {
213            return type_ == ValueType::INTS;
214        }
215        bool IsFloats() const
216        {
217            return type_ == ValueType::FLOATS;
218        }
219        bool IsString() const
220        {
221            return type_ == ValueType::STRING;
222        }
223        bool IsStrings() const
224        {
225            return type_ == ValueType::STRINGS;
226        }
227        bool IsBool() const
228        {
229            return type_ == ValueType::BOOL;
230        }
231        bool IsMap() const
232        {
233            return type_ == ValueType::MAP;
234        }
235        const ConfigItem& operator[](const std::string& key) const
236        {
237            if (type_ != ValueType::MAP) {
238                return DEFAULT;
239            }
240            if (mapValue_->count(key) == 0) {
241                return DEFAULT;
242            }
243            return mapValue_->at(key);
244        }
245        const ConfigItem& GetProp(const std::string& key) const
246        {
247            if (!property_) {
248                return DEFAULT;
249            }
250            if (property_->count(key) == 0) {
251                return DEFAULT;
252            }
253            return property_->at(key);
254        }
255        static const ConfigItem DEFAULT;
256    };
257    static std::recursive_mutex mutex_;
258};
259} // namespace Rosen
260} // namespace OHOS
261
262#endif // OHOS_ROSEN_XML_CONFIG_BASE_H