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> ¤t, 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> ¤t, 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> ¤t, 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> ¤t, 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