• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "ast.h"
10 
11 #include <iomanip>
12 #include <set>
13 #include <sstream>
14 
15 #include "logger.h"
16 
17 using namespace OHOS::Hardware;
18 
AstObject(const AstObject & obj)19 AstObject::AstObject(const AstObject &obj) : AstObject(obj.name_, obj.type_, obj.stringValue_)
20 {
21     integerValue_ = obj.integerValue_;
22 }
23 
AstObject(std::string name,uint32_t type,uint64_t value)24 AstObject::AstObject(std::string name, uint32_t type, uint64_t value) :
25     type_(type),
26     name_(std::move(name)),
27     parent_(nullptr),
28     lineno_(0),
29     opCode_(0),
30     size_(0),
31     subSize_(0),
32     hash_(0),
33     integerValue_(value)
34 {
35 }
36 
AstObject(std::string name,uint32_t type,std::string value)37 AstObject::AstObject(std::string name, uint32_t type, std::string value) : AstObject(std::move(name), type, 0)
38 {
39     stringValue_ = std::move(value);
40 }
41 
AstObject(std::string name,uint32_t type,uint64_t value,const Token & bindToken)42 AstObject::AstObject(std::string name, uint32_t type, uint64_t value, const Token &bindToken) :
43     AstObject(std::move(name), type, value)
44 {
45     lineno_ = bindToken.lineNo;
46     src_ = bindToken.src;
47 
48     switch (type) {
49         case PARSEROP_UINT8:  /* fall-through */
50         case PARSEROP_UINT16: /* fall-through */
51         case PARSEROP_UINT32: /* fall-through */
52         case PARSEROP_UINT64:
53             this->type_ = FitIntegerValueType(value);
54             break;
55         default:
56             break;
57     }
58 }
59 
AstObject(std::string name,uint32_t type,std::string value,const Token & bindToken)60 AstObject::AstObject(std::string name, uint32_t type, std::string value, const Token &bindToken) :
61     AstObject(std::move(name), type, 0, bindToken)
62 {
63     stringValue_ = std::move(value);
64 }
65 
~AstObject()66 AstObject::~AstObject()
67 {
68     parent_ = nullptr;
69     next_ = nullptr;
70     child_ = nullptr;
71 }
72 
operator =(const AstObject & obj)73 AstObject& AstObject::operator=(const AstObject &obj)
74 {
75     if (this != &obj) {
76         type_ = obj.type_;
77         name_ = obj.name_;
78         parent_ = obj.parent_;
79         next_ = obj.next_;
80         child_ = obj.child_;
81         lineno_ = obj.lineno_;
82         src_ = obj.src_;
83         opCode_ = obj.opCode_;
84         size_ = obj.size_;
85         subSize_ = obj.subSize_;
86         hash_ = obj.hash_;
87         integerValue_ = obj.integerValue_;
88         stringValue_ = obj.stringValue_;
89     }
90 
91     return *this;
92 }
93 
FitIntegerValueType(uint64_t value)94 uint32_t AstObject::FitIntegerValueType(uint64_t value)
95 {
96     if (value <= UINT8_MAX) {
97         return PARSEROP_UINT8;
98     } else if (value <= UINT16_MAX) {
99         return PARSEROP_UINT16;
100     } else if (value <= UINT32_MAX) {
101         return PARSEROP_UINT32;
102     } else {
103         return PARSEROP_UINT64;
104     }
105 }
106 
AddChild(const std::shared_ptr<AstObject> & childObj)107 bool AstObject::AddChild(const std::shared_ptr<AstObject> &childObj)
108 {
109     if (childObj == nullptr) {
110         return false;
111     }
112     if (child_ == nullptr) {
113         child_ = childObj;
114         std::shared_ptr<AstObject> childNext = childObj;
115         while (childNext != nullptr) {
116             childNext->parent_ = this;
117             childNext = childNext->next_;
118         }
119     } else {
120         return child_->AddPeer(childObj);
121     }
122 
123     return true;
124 }
125 
AddPeer(std::shared_ptr<AstObject> peerObject)126 bool AstObject::AddPeer(std::shared_ptr<AstObject> peerObject)
127 {
128     if (peerObject == nullptr) {
129         return false;
130     }
131 
132     if (this == peerObject.get()) {
133         Logger().Error() << "add self as peer";
134         return false;
135     }
136 
137     if (next_ == nullptr) {
138         next_ = peerObject;
139     } else {
140         std::shared_ptr<AstObject> lastNode = next_;
141         while (lastNode->next_ != nullptr) {
142             lastNode = lastNode->next_;
143         }
144         lastNode->next_ = peerObject;
145     }
146 
147     std::shared_ptr<AstObject> peer = peerObject;
148     while (peer) {
149         peer->parent_ = parent_;
150         peer = peer->next_;
151     }
152 
153     return true;
154 }
155 
operator <<(std::ostream & stream,const AstObject & t)156 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const AstObject &t)
157 {
158     if (t.type_ == PARSEROP_CONFNODE) {
159         auto node = static_cast<const ConfigNode *>(&t);
160         stream << *node;
161         return stream;
162     } else if (t.type_ == PARSEROP_CONFTERM) {
163         auto term = static_cast<const ConfigTerm *>(&t);
164         stream << *term;
165         return stream;
166     }
167 
168     if (t.name_.empty()) {
169         stream << "|_";
170     } else {
171         stream << t.name_;
172     }
173     switch (t.type_) {
174         case PARSEROP_UINT8:
175             stream << "uint8 0x" << std::hex << t.integerValue_;
176             break;
177         case PARSEROP_UINT16:
178             stream << "uint16 0x" << std::hex << t.integerValue_;
179             break;
180         case PARSEROP_UINT32:
181             stream << "uint32 0x" << std::hex << t.integerValue_;
182             break;
183         case PARSEROP_UINT64:
184             stream << "uint64 0x" << std::hex << t.integerValue_;
185             break;
186         case PARSEROP_STRING:
187             stream << "string \"" << t.stringValue_ << "\"";
188             break;
189         case PARSEROP_ARRAY:
190             stream << "array";
191             break;
192         case PARSEROP_NODEREF:
193             stream << "noderef " << t.stringValue_;
194             break;
195         case PARSEROP_DELETE:
196             stream << "delete";
197             break;
198         default:
199             break;
200     }
201     return stream;
202 }
203 
Merge(std::shared_ptr<AstObject> & srcObj)204 bool AstObject::Merge(std::shared_ptr<AstObject> &srcObj)
205 {
206     if (srcObj->name_ != name_) {
207         Logger().Error() << this->SourceInfo() << "merge different node to" << srcObj->SourceInfo();
208         return false;
209     }
210 
211     if (srcObj->type_ != type_) {
212         Logger().Error() << this->SourceInfo() << "conflict type with " << srcObj->SourceInfo();
213         return false;
214     }
215 
216     src_ = srcObj->src_;
217     lineno_ = srcObj->lineno_;
218     stringValue_ = srcObj->stringValue_;
219     integerValue_ = srcObj->integerValue_;
220 
221     return true;
222 }
223 
Copy(std::shared_ptr<AstObject> src,bool overwrite)224 bool AstObject::Copy(std::shared_ptr<AstObject> src, bool overwrite)
225 {
226     if (src == nullptr) {
227         return false;
228     }
229 
230     if (overwrite) {
231         src_ = src->src_;
232         lineno_ = src->lineno_;
233         integerValue_ = src->integerValue_;
234         stringValue_ = src->stringValue_;
235     }
236 
237     return true;
238 }
239 
Move(std::shared_ptr<AstObject> src)240 bool AstObject::Move(std::shared_ptr<AstObject> src)
241 {
242     if (!Copy(src, true)) {
243         return false;
244     }
245     src->Separate();
246     return true;
247 }
248 
SourceInfo()249 std::string AstObject::SourceInfo()
250 {
251     std::stringstream o;
252     o << src_->c_str() << ":" << lineno_ << " ";
253     return o.str();
254 }
255 
Remove()256 void AstObject::Remove()
257 {
258     Separate();
259     child_ = nullptr;
260     next_ = nullptr;
261 }
262 
Lookup(const std::string & name,uint32_t type) const263 std::shared_ptr<AstObject> AstObject::Lookup(const std::string &name, uint32_t type) const
264 {
265     auto peer = child_;
266     while (peer != nullptr) {
267         if (peer->name_ == name && (type == 0 || peer->type_ == type)) {
268             return peer;
269         }
270 
271         peer = peer->next_;
272     }
273 
274     return nullptr;
275 }
276 
IsNumber() const277 bool AstObject::IsNumber() const
278 {
279     return type_ >= PARSEROP_UINT8 && type_ <= PARSEROP_UINT64;
280 }
281 
IsNode() const282 bool AstObject::IsNode() const
283 {
284     return type_ == PARSEROP_CONFNODE;
285 }
286 
IsTerm() const287 bool AstObject::IsTerm() const
288 {
289     return type_ == PARSEROP_CONFTERM;
290 }
291 
IsArray() const292 bool AstObject::IsArray() const
293 {
294     return type_ == PARSEROP_ARRAY;
295 }
296 
Separate()297 void AstObject::Separate()
298 {
299     if (parent_ == nullptr) {
300         return;
301     }
302     if (parent_->child_.get() == this) {
303         parent_->child_ = next_; // decref this
304         next_ = nullptr;
305         return;
306     }
307 
308     auto pre = parent_->child_;
309     while (pre != nullptr) {
310         if (pre->next_.get() == this) {
311             pre->next_ = pre->next_->next_; // decref this
312             break;
313         }
314 
315         pre = pre->next_;
316     }
317     next_ = nullptr;
318 }
319 
SetParent(AstObject * parent)320 void AstObject::SetParent(AstObject *parent)
321 {
322     parent_ = parent;
323 }
324 
SetSize(uint32_t size)325 void AstObject::SetSize(uint32_t size)
326 {
327     size_ = size;
328 }
329 
SetSubSize(uint32_t size)330 void AstObject::SetSubSize(uint32_t size)
331 {
332     subSize_ = size;
333 }
334 
GetSubSize()335 uint32_t AstObject::GetSubSize()
336 {
337     return subSize_;
338 }
339 
SetHash(uint32_t hash)340 void AstObject::SetHash(uint32_t hash)
341 {
342     hash_ = hash;
343 }
344 
GetSize()345 uint32_t AstObject::GetSize()
346 {
347     return size_;
348 }
349 
GetHash()350 uint32_t AstObject::GetHash()
351 {
352     return hash_;
353 }
354 
Next()355 std::shared_ptr<AstObject> AstObject::Next()
356 {
357     return next_;
358 }
359 
Child()360 std::shared_ptr<AstObject> AstObject::Child()
361 {
362     return child_;
363 }
364 
Name()365 const std::string &AstObject::Name()
366 {
367     return name_;
368 }
369 
StringValue()370 const std::string &AstObject::StringValue()
371 {
372     return stringValue_;
373 }
374 
IntegerValue()375 uint64_t AstObject::IntegerValue()
376 {
377     return integerValue_;
378 }
379 
Type()380 uint32_t AstObject::Type()
381 {
382     return type_;
383 }
384 
OpCode()385 uint8_t AstObject::OpCode()
386 {
387     return opCode_;
388 }
389 
SetOpCode(uint8_t opcode)390 void AstObject::SetOpCode(uint8_t opcode)
391 {
392     opCode_ = opcode;
393 }
394 
HasDuplicateChild()395 bool AstObject::HasDuplicateChild()
396 {
397     return false;
398 }
399 
IsElders(const std::shared_ptr<AstObject> & child)400 bool AstObject::IsElders(const std::shared_ptr<AstObject> &child)
401 {
402     auto p = child.get();
403     while (p != nullptr) {
404         if (p == this) {
405             return true;
406         }
407         p = p->parent_;
408     }
409     return false;
410 }
411 
Parent()412 std::shared_ptr<AstObject> AstObject::Parent()
413 {
414     return std::shared_ptr<AstObject>(parent_, [](auto p) {});
415 }
416 
ConfigNode(const ConfigNode & node)417 ConfigNode::ConfigNode(const ConfigNode &node) : ConfigNode(node.name_, node.nodeType_, node.refNodePath_)
418 {
419     auto child = node.child_;
420     while (child != nullptr) {
421         AstObject::AddChild(AstObjectFactory::Build(child));
422         child = child->Next();
423     }
424 }
425 
ConfigNode(std::string name,uint32_t nodeType,std::string refName)426 ConfigNode::ConfigNode(std::string name, uint32_t nodeType, std::string refName) :
427     AstObject(std::move(name), PARSEROP_CONFNODE, ""),
428     refNodePath_(std::move(refName)),
429     nodeType_(nodeType),
430     inheritIndex_(0),
431     inheritCount_(0),
432     templateSignNum_(0)
433 {
434 }
435 
ConfigNode(Token & name,uint32_t nodeType,std::string refName)436 ConfigNode::ConfigNode(Token &name, uint32_t nodeType, std::string refName) :
437     AstObject(name.strval, PARSEROP_CONFNODE, 0, name),
438     refNodePath_(std::move(refName)),
439     nodeType_(nodeType),
440     inheritIndex_(0),
441     inheritCount_(0),
442     templateSignNum_(0)
443 {
444 }
445 
operator =(const ConfigNode & node)446 ConfigNode& ConfigNode::operator=(const ConfigNode &node)
447 {
448     if (this != &node) {
449         refNodePath_ = node.refNodePath_;
450         nodeType_ = node.nodeType_;
451         inheritIndex_ = node.inheritIndex_;
452         inheritCount_ = node.inheritCount_;
453         templateSignNum_ = node.templateSignNum_;
454         subClasses_ = node.subClasses_;
455     }
456 
457     return *this;
458 }
459 
NodeTypeToStr(uint32_t type)460 const std::string &ConfigNode::NodeTypeToStr(uint32_t type)
461 {
462     static std::map<uint32_t, std::string> type2StringMap = {
463         {NODE_NOREF,     ""             },
464         { NODE_COPY,     "NodeCopy"     },
465         { NODE_REF,      "NodeReference"},
466         { NODE_DELETE,   "NodeDelete"   },
467         { NODE_INHERIT,  "NodeInherit"  },
468         { NODE_TEMPLATE, "NodeTemplate" },
469     };
470     return type2StringMap[type];
471 }
472 
operator <<(std::ostream & stream,const ConfigNode & t)473 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const ConfigNode &t)
474 {
475     stream << "[node] " << t.name_.data() << " " << ConfigNode::NodeTypeToStr(t.nodeType_).data() << " "
476            << t.refNodePath_.data();
477     return stream;
478 }
479 
CastFrom(const std::shared_ptr<AstObject> & astObject)480 ConfigNode *ConfigNode::CastFrom(const std::shared_ptr<AstObject> &astObject)
481 {
482     return dynamic_cast<ConfigNode *>(astObject.get());
483 }
484 
GetNodeType() const485 uint32_t ConfigNode::GetNodeType() const
486 {
487     return nodeType_;
488 }
489 
GetRefPath()490 const std::string &ConfigNode::GetRefPath()
491 {
492     return refNodePath_;
493 }
494 
Merge(std::shared_ptr<AstObject> & srcObj)495 bool ConfigNode::Merge(std::shared_ptr<AstObject> &srcObj)
496 {
497     if (srcObj == nullptr) {
498         return true;
499     }
500     if (!srcObj->IsNode() || srcObj->Name() != name_) {
501         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
502         return false;
503     }
504 
505     auto srcNode = ConfigNode::CastFrom(srcObj);
506     if (srcNode->GetNodeType() == DELETE) {
507         srcObj->Separate();
508         this->Separate();
509         return true;
510     }
511 
512     nodeType_ = srcNode->nodeType_;
513     refNodePath_ = srcNode->refNodePath_;
514 
515     auto childSrc = srcObj->Child();
516     while (childSrc != nullptr) {
517         auto childSrcNext = childSrc->Next();
518         auto childDst = Lookup(childSrc->Name(), childSrc->Type());
519         if (childDst == nullptr) {
520             childSrc->Separate();
521             AddChild(childSrc);
522         } else {
523             if (!childDst->Merge(childSrc)) {
524                 return false;
525             }
526         }
527         childSrc = childSrcNext;
528     }
529     return true;
530 }
531 
SetNodeType(uint32_t nodeType)532 void ConfigNode::SetNodeType(uint32_t nodeType)
533 {
534     nodeType_ = nodeType;
535 }
536 
SetRefPath(std::string ref)537 void ConfigNode::SetRefPath(std::string ref)
538 {
539     refNodePath_ = std::move(ref);
540 }
541 
HasDuplicateChild()542 bool ConfigNode::HasDuplicateChild()
543 {
544     std::map<std::string, std::shared_ptr<AstObject>> symMap;
545     auto child = child_;
546     while (child != nullptr) {
547         auto sym = symMap.find(child->Name());
548         if (sym != symMap.end()) {
549             Logger().Error() << child->SourceInfo() << "redefined, first definition at " << sym->second->SourceInfo();
550             return true;
551         }
552         symMap[child->Name()] = child;
553         child = child->Next();
554     }
555 
556     return false;
557 }
558 
InheritExpand(const std::shared_ptr<AstObject> & refObj)559 bool ConfigNode::InheritExpand(const std::shared_ptr<AstObject> &refObj)
560 {
561     if (refObj == nullptr) {
562         Logger().Error() << SourceInfo() << "inherit invalid node: " << refNodePath_;
563         return false;
564     }
565 
566     if (!Copy(refObj, false)) {
567         return false;
568     }
569 
570     auto templateNode = ConfigNode::CastFrom(refObj);
571     if (!Compare(*templateNode)) {
572         return false;
573     }
574     inheritIndex_ = templateNode->inheritCount_++;
575     templateNode->subClasses_.push_back(this);
576     return true;
577 }
578 
RefExpand(const std::shared_ptr<AstObject> & refObj)579 bool ConfigNode::RefExpand(const std::shared_ptr<AstObject> &refObj)
580 {
581     if (nodeType_ == NODE_DELETE) {
582         this->Separate();
583         return true;
584     }
585 
586     if (refObj->IsElders(std::shared_ptr<AstObject>(this, [](auto p) {}))) {
587         Logger().Error() << SourceInfo() << "circular reference " << refObj->SourceInfo();
588         return false;
589     }
590 
591     bool ret = true;
592     if (nodeType_ == NODE_REF) {
593         ret = NodeRefExpand(refObj);
594     } else if (nodeType_ == NODE_COPY) {
595         ret = NodeCopyExpand(refObj);
596     }
597 
598     return ret;
599 }
600 
Copy(std::shared_ptr<AstObject> src,bool overwrite)601 bool ConfigNode::Copy(std::shared_ptr<AstObject> src, bool overwrite)
602 {
603     auto child = src->Child();
604     while (child != nullptr) {
605         auto dst = Lookup(child->Name(), child->Type());
606         if (dst == nullptr) {
607             AddChild(AstObjectFactory::Build(child));
608         } else {
609             if (!dst->Copy(child, overwrite)) {
610                 return false;
611             }
612         }
613         child = child->Next();
614     }
615 
616     return true;
617 }
618 
Move(std::shared_ptr<AstObject> src)619 bool ConfigNode::Move(std::shared_ptr<AstObject> src)
620 {
621     return AstObject::Move(src);
622 }
623 
NodeRefExpand(const std::shared_ptr<AstObject> & ref)624 bool ConfigNode::NodeRefExpand(const std::shared_ptr<AstObject> &ref)
625 {
626     if (ref == nullptr) {
627         Logger().Error() << SourceInfo() << "reference node '" << refNodePath_ << "' not exist";
628         return false;
629     }
630     return ref->Move(std::shared_ptr<AstObject>(this, [](AstObject *p) { (void)p; }));
631 }
632 
NodeCopyExpand(const std::shared_ptr<AstObject> & ref)633 bool ConfigNode::NodeCopyExpand(const std::shared_ptr<AstObject> &ref)
634 {
635     if (ref == nullptr) {
636         Logger().Error() << SourceInfo() << "copy node '" << refNodePath_ << "' not exist";
637         return false;
638     }
639     this->nodeType_ = NODE_NOREF;
640     return Copy(ref, false);
641 }
642 
Compare(ConfigNode & other)643 bool ConfigNode::Compare(ConfigNode &other)
644 {
645     auto objChild = child_;
646     while (objChild != nullptr) {
647         auto baseObj = Lookup(objChild->Name(), objChild->Type());
648         if (baseObj == nullptr) {
649             Logger().Error() << objChild->SourceInfo() << "not in template node: " << other.SourceInfo();
650             return false;
651         }
652         if (objChild->IsNode()) {
653             return ConfigNode::CastFrom(objChild)->Compare(*ConfigNode::CastFrom(baseObj));
654         }
655 
656         objChild = objChild->Next();
657     }
658     return true;
659 }
660 
InheritIndex()661 uint32_t ConfigNode::InheritIndex()
662 {
663     return inheritIndex_;
664 }
665 
InheritCount()666 uint32_t ConfigNode::InheritCount()
667 {
668     return inheritCount_;
669 }
670 
TemplateSignNum()671 uint32_t ConfigNode::TemplateSignNum()
672 {
673     return templateSignNum_;
674 }
675 
SetTemplateSignNum(uint32_t sigNum)676 void ConfigNode::SetTemplateSignNum(uint32_t sigNum)
677 {
678     templateSignNum_ = sigNum;
679 }
680 
SubClasses()681 const std::list<AstObject *> &ConfigNode::SubClasses()
682 {
683     return subClasses_;
684 }
685 
ConfigTerm(const ConfigTerm & term)686 ConfigTerm::ConfigTerm(const ConfigTerm &term) : ConfigTerm(term.name_, nullptr)
687 {
688     AstObject::AddChild(AstObjectFactory::Build(term.child_));
689 }
690 
ConfigTerm(std::string name,const std::shared_ptr<AstObject> & value)691 ConfigTerm::ConfigTerm(std::string name, const std::shared_ptr<AstObject> &value) :
692     AstObject(std::move(name), PARSEROP_CONFTERM, 0),
693     signNum_(0)
694 {
695     if (value != nullptr) {
696         child_ = value;
697         value->SetParent(this);
698     }
699 }
700 
ConfigTerm(Token & name,const std::shared_ptr<AstObject> & value)701 ConfigTerm::ConfigTerm(Token &name, const std::shared_ptr<AstObject> &value) :
702     AstObject(name.strval, PARSEROP_CONFTERM, 0, name),
703     signNum_(0)
704 {
705     if (value != nullptr) {
706         child_ = value;
707         value->SetParent(this);
708     }
709 }
710 
operator =(const ConfigTerm & term)711 ConfigTerm& ConfigTerm::operator=(const ConfigTerm &term)
712 {
713     if (this != &term) {
714         refNode_ = term.refNode_;
715         signNum_ = term.signNum_;
716     }
717 
718     return *this;
719 }
720 
operator <<(std::ostream & stream,const ConfigTerm & t)721 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const ConfigTerm &t)
722 {
723     stream << "[term] " << t.name_.data();
724     return stream;
725 }
726 
CastFrom(const std::shared_ptr<AstObject> & astObject)727 ConfigTerm *ConfigTerm::CastFrom(const std::shared_ptr<AstObject> &astObject)
728 {
729     return dynamic_cast<ConfigTerm *>(astObject.get());
730 }
731 
Merge(std::shared_ptr<AstObject> & srcObj)732 bool ConfigTerm::Merge(std::shared_ptr<AstObject> &srcObj)
733 {
734     if (!srcObj->IsTerm()) {
735         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
736         return false;
737     }
738 
739     auto value = srcObj->Child();
740     srcObj->Child()->Separate();
741     child_ = nullptr;
742     AddChild(value);
743     return true;
744 }
745 
RefExpand(const std::shared_ptr<AstObject> refObj)746 bool ConfigTerm::RefExpand(const std::shared_ptr<AstObject> refObj)
747 {
748     if (child_->Type() == PARSEROP_DELETE) {
749         this->Separate();
750         return true;
751     }
752 
753     if (child_->Type() != PARSEROP_NODEREF) {
754         return true;
755     }
756 
757     if (refObj == nullptr || !refObj->IsNode() || ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_REF ||
758         ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_TEMPLATE ||
759         ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_DELETE) {
760         Logger().Error() << SourceInfo() << "reference invalid node '" << child_->StringValue() << '\'';
761         return false;
762     }
763 
764     refNode_ = refObj;
765     return true;
766 }
767 
Copy(std::shared_ptr<AstObject> src,bool overwrite)768 bool ConfigTerm::Copy(std::shared_ptr<AstObject> src, bool overwrite)
769 {
770     if (!overwrite) {
771         return true;
772     }
773     if (child_->Type() != src->Child()->Type() && (!child_->IsNumber() || !src->Child()->IsNumber())) {
774         Logger().Error() << src->SourceInfo() << "overwrite different type with:" << child_->SourceInfo();
775         return false;
776     }
777     return child_->Copy(src->Child(), overwrite);
778 }
779 
Move(std::shared_ptr<AstObject> src)780 bool ConfigTerm::Move(std::shared_ptr<AstObject> src)
781 {
782     return child_->Move(src->Child());
783 }
784 
RefNode()785 std::weak_ptr<AstObject> ConfigTerm::RefNode()
786 {
787     return refNode_;
788 }
789 
SetSigNum(uint32_t sigNum)790 void ConfigTerm::SetSigNum(uint32_t sigNum)
791 {
792     signNum_ = sigNum;
793 }
794 
SigNum()795 uint32_t ConfigTerm::SigNum()
796 {
797     return signNum_;
798 }
799 
ConfigArray()800 ConfigArray::ConfigArray() : AstObject("", PARSEROP_ARRAY, 0), arrayType_(0), arraySize_(0)
801 {
802 }
803 
ConfigArray(const ConfigArray & array)804 ConfigArray::ConfigArray(const ConfigArray &array) : ConfigArray()
805 {
806     auto child = array.child_;
807     while (child != nullptr) {
808         AstObject::AddChild(AstObjectFactory::Build(child));
809         child = child->Next();
810     }
811     arraySize_ = array.arraySize_;
812     arrayType_ = array.arrayType_;
813 }
814 
ConfigArray(const Token & bindToken)815 ConfigArray::ConfigArray(const Token &bindToken) :
816     AstObject("", PARSEROP_ARRAY, 0, bindToken),
817     arrayType_(0),
818     arraySize_(0) {};
819 
operator =(const ConfigArray & array)820 ConfigArray& ConfigArray::operator=(const ConfigArray &array)
821 {
822     if (this != &array) {
823         arrayType_ = array.arrayType_;
824         arraySize_ = array.arraySize_;
825     }
826 
827     return *this;
828 }
829 
AddChild(const std::shared_ptr<AstObject> & childObj)830 bool ConfigArray::AddChild(const std::shared_ptr<AstObject> &childObj)
831 {
832     if (AstObject::AddChild(childObj)) {
833         arraySize_++;
834         arrayType_ = std::max(arrayType_, childObj->Type());
835         return true;
836     } else {
837         return false;
838     }
839 }
840 
Merge(std::shared_ptr<AstObject> & srcObj)841 bool ConfigArray::Merge(std::shared_ptr<AstObject> &srcObj)
842 {
843     if (!srcObj->IsArray()) {
844         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
845         return false;
846     }
847 
848     auto value = srcObj->Child();
849     value->Separate();
850     child_ = value;
851     return true;
852 }
853 
Copy(std::shared_ptr<AstObject> src,bool overwrite)854 bool ConfigArray::Copy(std::shared_ptr<AstObject> src, bool overwrite)
855 {
856     if (!overwrite) {
857         return true;
858     }
859     auto array = ConfigArray::CastFrom(src);
860     child_ = nullptr;
861     auto t = array->child_;
862     while (t != nullptr) {
863         AddChild(AstObjectFactory::Build(t));
864     }
865     return true;
866 }
867 
CastFrom(const std::shared_ptr<AstObject> & astObject)868 ConfigArray *ConfigArray::CastFrom(const std::shared_ptr<AstObject> &astObject)
869 {
870     return static_cast<ConfigArray *>(astObject.get());
871 }
872 
ArraySize()873 uint16_t ConfigArray::ArraySize()
874 {
875     return arraySize_;
876 }
877 
ArrayType()878 uint16_t ConfigArray::ArrayType()
879 {
880     return arrayType_;
881 }
882 
Build(std::shared_ptr<AstObject> object)883 std::shared_ptr<AstObject> AstObjectFactory::Build(std::shared_ptr<AstObject> object)
884 {
885     switch (object->Type()) {
886         case PARSEROP_CONFNODE:
887             return std::make_shared<ConfigNode>(*ConfigNode::CastFrom(object));
888         case PARSEROP_CONFTERM:
889             return std::make_shared<ConfigTerm>(*ConfigTerm::CastFrom(object));
890         case PARSEROP_ARRAY:
891             return std::make_shared<ConfigArray>(*ConfigArray::CastFrom(object));
892         default:
893             return std::make_shared<AstObject>(*object);
894     }
895 }
896 
Dump(const std::string & prefix)897 void Ast::Dump(const std::string &prefix)
898 {
899     Logger().Debug() << "Dump " << prefix << " AST:";
900     WalkForward([](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
901         Logger().Debug() << ::std::setw(walkDepth * 4) << " " << *current;
902         return NOERR;
903     });
904 }
905 
GetAstRoot()906 std::shared_ptr<AstObject> Ast::GetAstRoot()
907 {
908     return astRoot_;
909 }
910 
Merge(const std::list<std::shared_ptr<Ast>> & astList)911 bool Ast::Merge(const std::list<std::shared_ptr<Ast>> &astList)
912 {
913     if (!RedefineCheck()) {
914         return false;
915     }
916     for (auto &astIt : astList) {
917         if (!astIt->RedefineCheck()) {
918             return false;
919         }
920         if (astRoot_ == nullptr) {
921             astRoot_ = astIt->GetAstRoot();
922             continue;
923         }
924         Dump("merge this");
925         astIt->Dump("tobe merge");
926         if (!astRoot_->Merge(astIt->astRoot_)) {
927             return false;
928         }
929         astIt->Dump("merged");
930     }
931     return true;
932 }
933 
Expand()934 bool Ast::Expand()
935 {
936     if (!RedefineCheck()) {
937         return false;
938     }
939 
940     if (astRoot_->Lookup("module", PARSEROP_CONFTERM) == nullptr) {
941         Logger().Error() << astRoot_->SourceInfo() << "miss 'module' attribute under root node";
942         return false;
943     }
944 
945     if (!NodeExpand()) {
946         return false;
947     }
948 
949     if (!InheritExpand()) {
950         return false;
951     };
952 
953     Dump("expanded");
954     return true;
955 }
956 
NodeExpand()957 bool Ast::NodeExpand()
958 {
959     return WalkBackward([this](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
960         (void)walkDepth;
961         if (current->IsNode()) {
962             auto node = ConfigNode::CastFrom(current);
963             if (node->GetNodeType() == NODE_DELETE) {
964                 current->Remove();
965                 return NOERR;
966             }
967             if (node->GetNodeType() != NODE_REF && node->GetNodeType() != NODE_COPY) {
968                 return NOERR;
969             }
970             // current node maybe deleted after reference expand, never use it after this
971             auto ret = node->RefExpand(Lookup(current, node->GetRefPath()));
972             if (!ret) {
973                 return EFAIL;
974             }
975         } else if (current->IsTerm()) {
976             std::shared_ptr<AstObject> ref;
977             if (current->child_->Type() == PARSEROP_DELETE) {
978                 current->Remove();
979                 return NOERR;
980             }
981             if (current->child_->Type() == PARSEROP_NODEREF) {
982                 ref = Lookup(current, current->child_->StringValue());
983                 if (!ConfigTerm::CastFrom(current)->RefExpand(ref)) {
984                     return EFAIL;
985                 }
986             }
987         }
988         return NOERR;
989     });
990 }
991 
InheritExpand()992 bool Ast::InheritExpand()
993 {
994     return WalkForward([this](const std::shared_ptr<AstObject> &current, int32_t) -> int32_t {
995         if (current->IsNode()) {
996             auto node = ConfigNode::CastFrom(current);
997             if (node->GetNodeType() != NODE_INHERIT) {
998                 return NOERR;
999             }
1000             auto inherit = Lookup(current, node->GetRefPath());
1001             if (!node->InheritExpand(inherit)) {
1002                 return EFAIL;
1003             }
1004         }
1005 
1006         return NOERR;
1007     });
1008 }
1009 
RedefineCheck()1010 bool Ast::RedefineCheck()
1011 {
1012     if (redefineChecked_) {
1013         return true;
1014     }
1015 
1016     bool ret = WalkForward([](const std::shared_ptr<AstObject> &current, int32_t) -> int32_t {
1017         if (current->IsNode() && current->HasDuplicateChild()) {
1018             return EFAIL;
1019         }
1020 
1021         return NOERR;
1022     });
1023 
1024     redefineChecked_ = true;
1025     return ret;
1026 }
1027 
Lookup(const std::shared_ptr<AstObject> & startObj,const std::string & path)1028 std::shared_ptr<AstObject> Ast::Lookup(const std::shared_ptr<AstObject> &startObj, const std::string &path)
1029 {
1030     if (path.find('.') == std::string::npos) {
1031         return startObj->parent_->Lookup(path);
1032     }
1033 
1034     auto splitPath = SplitNodePath(path, '.');
1035     if (splitPath.front() != astRoot_->name_) {
1036         Logger().Error() << "lookup ast with invalid path, which not begin with 'root': " << path;
1037         return nullptr;
1038     }
1039     splitPath.erase(splitPath.begin());
1040 
1041     std::shared_ptr<AstObject> target = astRoot_;
1042     std::shared_ptr<AstObject> child = astRoot_->Child();
1043     for (auto &it : splitPath) {
1044         // look up children
1045         target = target->Lookup(it);
1046         if (target == nullptr) {
1047             break;
1048         }
1049     }
1050 
1051     return target;
1052 }
1053 
SplitNodePath(const std::string & path,char separator)1054 std::list<std::string> Ast::SplitNodePath(const std::string &path, char separator)
1055 {
1056     std::list<std::string> splitList;
1057     std::string temp;
1058     for (auto c : path) {
1059         if (c != separator) {
1060             temp.push_back(c);
1061         } else {
1062             if (temp.empty()) {
1063                 splitList.clear();
1064                 break;
1065             }
1066             splitList.push_back(temp);
1067             temp.clear();
1068         }
1069     }
1070 
1071     if (temp.empty()) {
1072         splitList.push_back(path);
1073     } else {
1074         splitList.push_back(temp);
1075     }
1076     return splitList;
1077 }
1078