1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #ifndef HC_GEN_AST_H
10 #define HC_GEN_AST_H
11 
12 #include <list>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "token.h"
18 #include "types.h"
19 
20 namespace OHOS {
21 namespace Hardware {
22 enum ObjectType {
23     PARSEROP_UINT8 = 0x01,
24     PARSEROP_UINT16,
25     PARSEROP_UINT32,
26     PARSEROP_UINT64,
27     PARSEROP_STRING,
28     PARSEROP_CONFNODE,
29     PARSEROP_CONFTERM,
30     PARSEROP_ARRAY,
31     PARSEROP_NODEREF,
32     PARSEROP_DELETE,
33 };
34 
35 enum NodeRefType {
36     NODE_NOREF = 0,
37     NODE_COPY,
38     NODE_REF,
39     NODE_DELETE,
40     NODE_TEMPLATE,
41     NODE_INHERIT,
42 };
43 
44 class AstObject {
45 public:
46     friend class Ast;
47 
48     AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const std::string &strValue,
49         uint32_t lineno, const std::shared_ptr<std::string> &src);
50 
51     AstObject(const std::string &name, uint32_t type, uint64_t integerValue);
52 
53     AstObject(const std::string &name, uint32_t type, const std::string &strValue);
54 
55     AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const Token &bindToken);
56 
57     AstObject(const std::string &name, uint32_t type, const std::string &strValue, const Token &bindToken);
58 
59     AstObject(const AstObject &obj);
60 
61     virtual ~AstObject();
62 
63     AstObject &operator=(const AstObject &obj);
64 
65     virtual bool AddChild(const std::shared_ptr<AstObject> &childObj);
66 
67     virtual bool AddPeer(std::shared_ptr<AstObject> peerObject);
68 
69     friend std::ostream &operator<<(std::ostream &stream, const AstObject &t);
70 
71     virtual bool Merge(std::shared_ptr<AstObject> &srcObj);
72 
73     virtual bool Copy(std::shared_ptr<AstObject> src, bool overwrite);
74 
75     virtual bool Move(std::shared_ptr<AstObject> src);
76 
77     void Remove();
78 
79     void Separate();
80 
81     std::shared_ptr<AstObject> Lookup(const std::string &name, uint32_t type = 0) const;
82 
83     bool IsElders(const std::shared_ptr<AstObject> &child) const;
84 
85     bool IsNumber() const;
86 
87     bool IsNode() const;
88 
89     bool IsTerm() const;
90 
91     bool IsArray() const;
92 
93     virtual std::string SourceInfo();
94 
95     void SetParent(AstObject *parent);
96 
97     void SetSize(uint32_t size);
98 
99     void SetSubSize(uint32_t size);
100 
101     void SetHash(uint32_t hash);
102 
103     uint32_t GetSize() const;
104 
105     uint32_t GetSubSize() const;
106 
107     uint32_t GetHash() const;
108 
109     std::shared_ptr<AstObject> Child();
110 
111     std::shared_ptr<AstObject> Next();
112 
113     virtual const std::string &Name();
114 
115     const std::string &StringValue() const;
116 
117     uint64_t IntegerValue() const;
118 
119     virtual uint32_t Type();
120 
121     uint8_t OpCode() const;
122 
123     void SetOpCode(uint8_t opcode);
124 
125     virtual bool HasDuplicateChild();
126 
127     std::shared_ptr<AstObject> Parent() const;
128 
129 protected:
130     uint32_t type_;
131     std::string name_;
132     AstObject *parent_;
133     std::shared_ptr<AstObject> next_;
134     std::shared_ptr<AstObject> child_;
135     uint32_t lineno_;
136     std::shared_ptr<std::string> src_;
137     uint8_t opCode_;
138     uint32_t size_;
139     uint32_t subSize_;
140     uint32_t hash_;
141     uint64_t integerValue_;
142     std::string stringValue_;
143 
144 private:
145     static uint32_t FitIntegerValueType(uint64_t value);
146 };
147 
148 class ConfigNode : public AstObject {
149 public:
150     ConfigNode(const ConfigNode &node);
151 
152     ConfigNode(const std::string &name, uint32_t nodeType, const std::string &refName);
153 
154     ConfigNode(Token &name, uint32_t nodeType, const std::string &refName);
155 
156     ~ConfigNode() override = default;
157 
158     ConfigNode &operator=(const ConfigNode &node);
159 
160     friend std::ostream &operator<<(std::ostream &stream, const ConfigNode &t);
161 
162     bool Merge(std::shared_ptr<AstObject> &srcObj) override;
163 
164     static ConfigNode *CastFrom(const std::shared_ptr<AstObject> &astObject);
165 
166     uint32_t GetNodeType() const;
167 
168     const std::string &GetRefPath() const;
169 
170     void SetNodeType(uint32_t nodeType);
171 
172     void SetRefPath(const std::string &ref);
173 
174     static const std::string &NodeTypeToStr(uint32_t type);
175 
176     bool HasDuplicateChild() override;
177 
178     bool InheritExpand(const std::shared_ptr<AstObject> &refObj);
179 
180     bool RefExpand(const std::shared_ptr<AstObject> &refObj);
181 
182     bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
183 
184     bool Move(std::shared_ptr<AstObject> src) override;
185 
186     bool Compare(ConfigNode &other) const;
187 
188     bool IsBaseNode();
189 
190     uint32_t InheritIndex() const;
191 
192     uint32_t InheritCount() const;
193 
194     uint32_t TemplateSignNum() const;
195 
196     void SetTemplateSignNum(uint32_t sigNum);
197 
198     const std::list<AstObject *> &SubClasses() const;
199 
200 private:
201     bool NodeRefExpand(const std::shared_ptr<AstObject> &ref);
202 
203     bool NodeCopyExpand(const std::shared_ptr<AstObject> &ref);
204 
205     std::string refNodePath_;
206     uint32_t nodeType_;
207     uint32_t inheritIndex_;
208     uint32_t inheritCount_;
209     uint32_t templateSignNum_;
210     std::list<AstObject *> subClasses_;
211 };
212 
213 class ConfigTerm : public AstObject {
214 public:
215     ConfigTerm(const ConfigTerm &term);
216 
217     ConfigTerm(const std::string &name, const std::shared_ptr<AstObject> &value);
218 
219     ConfigTerm(Token &name, const std::shared_ptr<AstObject> &value);
220 
221     ~ConfigTerm() override = default;
222 
223     ConfigTerm &operator=(const ConfigTerm &term);
224 
225     static ConfigTerm *CastFrom(const std::shared_ptr<AstObject> &astObject);
226 
227     bool Merge(std::shared_ptr<AstObject> &srcObj) override;
228 
229     friend std::ostream &operator<<(std::ostream &stream, const ConfigTerm &t);
230 
231     bool RefExpand(const std::shared_ptr<AstObject> refObj);
232 
233     bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
234 
235     bool Move(std::shared_ptr<AstObject> src) override;
236 
237     std::weak_ptr<AstObject> RefNode();
238 
239     uint32_t SigNum() const;
240 
241     void SetSigNum(uint32_t sigNum);
242 
243 private:
244     std::weak_ptr<AstObject> refNode_;
245     uint32_t signNum_;
246 };
247 
248 class ConfigArray : public AstObject {
249 public:
250     ConfigArray();
251 
252     ConfigArray(const ConfigArray &array);
253 
254     explicit ConfigArray(const Token &bindToken);
255 
256     ~ConfigArray() override = default;
257 
258     ConfigArray &operator=(const ConfigArray &array);
259 
260     static ConfigArray *CastFrom(const std::shared_ptr<AstObject> &astObject);
261 
262     bool AddChild(const std::shared_ptr<AstObject> &childObj) override;
263 
264     bool Merge(std::shared_ptr<AstObject> &srcObj) override;
265 
266     bool Copy(std::shared_ptr<AstObject> src, bool overwrite) override;
267 
268     uint16_t ArraySize() const;
269 
270     uint16_t ArrayType() const;
271 
272 private:
273     uint32_t arrayType_;
274     uint32_t arraySize_;
275 };
276 
277 class AstObjectFactory {
278 public:
279     static std::shared_ptr<AstObject> Build(std::shared_ptr<AstObject> object);
280 };
281 
282 class Ast {
283 public:
Ast(std::shared_ptr<AstObject> astRoot)284     explicit Ast(std::shared_ptr<AstObject> astRoot) : astRoot_(std::move(astRoot)), redefineChecked_(false) {}
285 
286     ~Ast() = default;
287 
288     std::shared_ptr<AstObject> GetAstRoot();
289 
290     bool Merge(const std::list<std::shared_ptr<Ast>> &astList);
291 
292     bool Expand();
293 
294     std::shared_ptr<AstObject> Lookup(const std::shared_ptr<AstObject> &startObj, const std::string &path);
295 
296     template <typename T>
WalkForward(const std::shared_ptr<AstObject> & startObject,T callback)297     static bool WalkForward(const std::shared_ptr<AstObject> &startObject, T callback)
298     {
299         std::shared_ptr<AstObject> forwardWalkObj = startObject;
300         int32_t walkDepth = 0;
301         bool preVisited = false;
302 
303         while (forwardWalkObj != nullptr) {
304             if (!preVisited) {
305                 int32_t ret = static_cast<int32_t>(callback(forwardWalkObj, walkDepth));
306                 if (ret && ret != EASTWALKBREAK) {
307                     return false;
308                 } else if (ret != EASTWALKBREAK && forwardWalkObj->child_ != nullptr) {
309                     /* when callback return EASTWALKBREAK, not walk current's child */
310                     walkDepth++;
311                     forwardWalkObj = forwardWalkObj->child_;
312                     continue;
313                 }
314             }
315             if (forwardWalkObj == startObject) {
316                 break;
317             }
318 
319             if (forwardWalkObj->next_ != nullptr) {
320                 forwardWalkObj = forwardWalkObj->next_;
321                 preVisited = false;
322             } else {
323                 forwardWalkObj = forwardWalkObj->Parent();
324                 preVisited = true;
325                 walkDepth--;
326             }
327         }
328 
329         return true;
330     }
331 
332     template <typename T>
WalkBackward(const std::shared_ptr<AstObject> & startObject,T callback)333     static bool WalkBackward(const std::shared_ptr<AstObject> &startObject, T callback)
334     {
335         std::shared_ptr<AstObject> backWalkObj = startObject;
336         std::shared_ptr<AstObject> next = nullptr;
337         std::shared_ptr<AstObject> parent = nullptr;
338         int32_t walkDepth = 0;
339         bool preVisited = false;
340 
341         while (backWalkObj != nullptr) {
342             if (backWalkObj->child_ == nullptr || preVisited) {
343                 next = backWalkObj->next_;
344                 parent = backWalkObj->Parent();
345                 /* can safe delete current in callback */
346                 if (callback(backWalkObj, walkDepth) != NOERR) {
347                     return false;
348                 }
349             } else {
350                 if (backWalkObj->child_) {
351                     walkDepth++;
352                     backWalkObj = backWalkObj->child_;
353                     continue;
354                 }
355             }
356             if (backWalkObj == startObject) {
357                 break;
358             }
359 
360             if (next != nullptr) {
361                 backWalkObj = next;
362                 preVisited = false;
363             } else {
364                 backWalkObj = parent;
365                 preVisited = true;
366                 walkDepth--;
367             }
368         }
369 
370         return true;
371     }
372 
373     template <typename T1, typename T2>
WalkRound(const std::shared_ptr<AstObject> & startObject,T1 forwardCallback,T2 backwardCallback)374     static bool WalkRound(const std::shared_ptr<AstObject> &startObject, T1 forwardCallback, T2 backwardCallback)
375     {
376         std::shared_ptr<AstObject> roundWalkObj = startObject;
377         int32_t walkDepth = 0;
378         bool preVisited = false;
379 
380         while (roundWalkObj != nullptr) {
381             if (preVisited) {
382                 if (backwardCallback(roundWalkObj, walkDepth) != NOERR) {
383                     return false;
384                 }
385             } else {
386                 uint32_t ret = forwardCallback(roundWalkObj, walkDepth);
387                 /* when callback return EASTWALKBREAK, not walk current's child */
388                 if (ret && ret != EASTWALKBREAK) {
389                     return false;
390                 } else if (!ret && roundWalkObj->child_ != nullptr) {
391                     walkDepth++;
392                     roundWalkObj = roundWalkObj->child_;
393                     continue;
394                 }
395             }
396             if (roundWalkObj == startObject) {
397                 break;
398             }
399 
400             if (roundWalkObj->next_) {
401                 roundWalkObj = roundWalkObj->next_;
402                 preVisited = false;
403             } else {
404                 roundWalkObj = roundWalkObj->Parent();
405                 preVisited = true;
406                 walkDepth--;
407             }
408         }
409 
410         return true;
411     }
412 
413     template <typename T>
WalkForward(T callback)414     bool WalkForward(T callback)
415     {
416         return WalkForward(astRoot_, callback);
417     }
418 
419     template <typename T>
WalkBackward(T callback)420     bool WalkBackward(T callback)
421     {
422         return WalkBackward(astRoot_, callback);
423     }
424 
425     template <typename T1, typename T2>
WalkRound(T1 forwardCallback,T2 backwardCallback)426     bool WalkRound(T1 forwardCallback, T2 backwardCallback)
427     {
428         return WalkRound(astRoot_, forwardCallback, backwardCallback);
429     }
430 
431     void Dump(const std::string &prefix = std::string());
432 
433 private:
434     bool RedefineCheck();
435 
436     bool NodeExpand();
437 
438     bool NodeExpandRef();
439 
440     bool NodeExpandDelete();
441 
442     bool NodeExpandTermRef();
443 
444     bool InheritExpand();
445 
446     static std::list<std::string> SplitNodePath(const std::string &path, char separator);
447 
448     std::shared_ptr<AstObject> astRoot_;
449     bool redefineChecked_;
450 };
451 
452 std::ostream &operator<<(std::ostream &stream, const AstObject &t);
453 std::ostream &operator<<(std::ostream &stream, const ConfigNode &t);
454 std::ostream &operator<<(std::ostream &stream, const ConfigTerm &t);
455 } // namespace Hardware
456 } // namespace OHOS
457 
458 #endif // HC_GEN_AST_H
459