node.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "node.h"
  2. #include <util/generic/algorithm.h>
  3. namespace NYql::NDom {
  4. namespace {
  5. inline bool StringLess(const TPair& x, const TPair& y) {
  6. return x.first.AsStringRef() < y.first.AsStringRef();
  7. }
  8. inline bool StringRefLess(const TPair& x, const TStringRef& y) {
  9. return x.first.AsStringRef() < y;
  10. }
  11. inline bool StringEquals(const TPair& x, const TPair& y) {
  12. return x.first.AsStringRef() == y.first.AsStringRef();
  13. }
  14. }
  15. template <bool NoSwap>
  16. TMapNode::TIterator<NoSwap>::TIterator(const TMapNode* parent)
  17. : Parent(const_cast<TMapNode*>(parent))
  18. , Index(-1)
  19. {}
  20. template <bool NoSwap>
  21. bool TMapNode::TIterator<NoSwap>::Skip() {
  22. if (Index + 1 == Parent->UniqueCount_) {
  23. return false;
  24. }
  25. ++Index;
  26. return true;
  27. }
  28. template <bool NoSwap>
  29. bool TMapNode::TIterator<NoSwap>::Next(TUnboxedValue& key) {
  30. if (!Skip())
  31. return false;
  32. if constexpr (NoSwap) {
  33. key = Parent->Items_[Index].first;
  34. } else {
  35. key = Parent->Items_[Index].second;
  36. }
  37. return true;
  38. }
  39. template <bool NoSwap>
  40. bool TMapNode::TIterator<NoSwap>::NextPair(TUnboxedValue& key, TUnboxedValue& payload) {
  41. if (!Next(key))
  42. return false;
  43. if constexpr (NoSwap) {
  44. payload = Parent->Items_[Index].second;
  45. } else {
  46. payload = Parent->Items_[Index].first;
  47. }
  48. return true;
  49. }
  50. TMapNode::TMapNode(TMapNode&& src)
  51. : Count_(src.Count_), UniqueCount_(src.UniqueCount_), Items_(src.Items_)
  52. {
  53. src.Count_ = src.UniqueCount_ = 0U;
  54. src.Items_ = nullptr;
  55. }
  56. TMapNode::TMapNode(const TPair* items, ui32 count)
  57. : Count_(count)
  58. , Items_((TPair*)UdfAllocateWithSize(sizeof(TPair) * count))
  59. {
  60. std::memset(Items_, 0, sizeof(TPair) * count);
  61. for (ui32 i = 0; i < count; ++i) {
  62. Items_[i] = std::move(items[i]);
  63. }
  64. StableSort(Items_, Items_ + count, StringLess);
  65. UniqueCount_ = Unique(Items_, Items_ + count, StringEquals) - Items_;
  66. for (ui32 i = UniqueCount_; i < count; ++i) {
  67. Items_[i].first.Clear();
  68. Items_[i].second.Clear();
  69. }
  70. }
  71. TMapNode::~TMapNode() {
  72. for (ui32 i = 0; i < UniqueCount_; ++i) {
  73. Items_[i].first.Clear();
  74. Items_[i].second.Clear();
  75. }
  76. UdfFreeWithSize(Items_, sizeof(TPair) * Count_);
  77. }
  78. ui64 TMapNode::GetDictLength() const {
  79. return UniqueCount_;
  80. }
  81. TUnboxedValue TMapNode::GetDictIterator() const {
  82. return TUnboxedValuePod(new TIterator<true>(this));
  83. }
  84. TUnboxedValue TMapNode::GetKeysIterator() const {
  85. return TUnboxedValuePod(new TIterator<true>(this));
  86. }
  87. TUnboxedValue TMapNode::GetPayloadsIterator() const {
  88. return TUnboxedValuePod(new TIterator<false>(this));
  89. }
  90. bool TMapNode::Contains(const TUnboxedValuePod& key) const {
  91. return BinarySearch(Items_, Items_ + UniqueCount_, std::make_pair(key, TUnboxedValuePod()), StringLess);
  92. }
  93. TUnboxedValue TMapNode::Lookup(const TUnboxedValuePod& key) const {
  94. return Lookup(key.AsStringRef());
  95. }
  96. TUnboxedValue TMapNode::Lookup(const TStringRef& key) const {
  97. const auto it = LowerBound(Items_, Items_ + UniqueCount_, key, StringRefLess);
  98. if (it == Items_ + UniqueCount_ || static_cast<TStringBuf>(it->first.AsStringRef()) != static_cast<TStringBuf>(key))
  99. return {};
  100. return it->second;
  101. }
  102. bool TMapNode::HasDictItems() const {
  103. return UniqueCount_ > 0ULL;
  104. }
  105. bool TMapNode::IsSortedDict() const {
  106. return true;
  107. }
  108. TStringRef TMapNode::GetResourceTag() const {
  109. return NodeResourceName;
  110. }
  111. void* TMapNode::GetResource() {
  112. return Items_;
  113. }
  114. TAttrNode::TAttrNode(const TUnboxedValue& map, TUnboxedValue&& value)
  115. : TMapNode(std::move(*static_cast<TMapNode*>(map.AsBoxed().Get()))), Value_(std::move(value))
  116. {}
  117. TAttrNode::TAttrNode(TUnboxedValue&& value, const TPair* items, ui32 count)
  118. : TMapNode(items, count), Value_(std::move(value))
  119. {}
  120. TUnboxedValue TAttrNode::GetVariantItem() const {
  121. return Value_;
  122. }
  123. TDebugPrinter::TDebugPrinter(const TUnboxedValuePod& node)
  124. : Node(node)
  125. {}
  126. IOutputStream& TDebugPrinter::Out(IOutputStream &o) const {
  127. switch (GetNodeType(Node)) {
  128. case ENodeType::Entity:
  129. o << "entity (#)";
  130. break;
  131. case ENodeType::Bool:
  132. o << "boolean (" << (Node.Get<bool>() ? "true" : "false") << ") value";
  133. break;
  134. case ENodeType::Int64:
  135. o << "integer (" << Node.Get<i64>() << ") value";
  136. break;
  137. case ENodeType::Uint64:
  138. o << "unsigned integer (" << Node.Get<ui64>() << ") value";
  139. break;
  140. case ENodeType::Double:
  141. o << "floating point (" << Node.Get<double>() << ") value";
  142. break;
  143. case ENodeType::String:
  144. if (const std::string_view str(Node.AsStringRef()); str.empty())
  145. o << "empty string";
  146. else if(Node.IsEmbedded() && str.cend() == std::find_if(str.cbegin(), str.cend(), [](char c){ return !std::isprint(c); }))
  147. o << "string '" << str << "' value";
  148. else
  149. o << "string value of size " << str.size();
  150. break;
  151. case ENodeType::List:
  152. if (Node.IsBoxed())
  153. o << "list of size " << Node.GetListLength();
  154. else
  155. o << "empty list";
  156. break;
  157. case ENodeType::Dict:
  158. if (Node.IsBoxed())
  159. o << "dict of size " << Node.GetDictLength();
  160. else
  161. o << "empty dict";
  162. break;
  163. case ENodeType::Attr:
  164. return TDebugPrinter(Node.GetVariantItem()).Out(o);
  165. default:
  166. o << "invalid node";
  167. break;
  168. }
  169. return o;
  170. }
  171. }