hash.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "node.h"
  2. #include "hash.h"
  3. #include <yql/essentials/public/udf/udf_type_ops.h>
  4. namespace NYql::NDom {
  5. using namespace NUdf;
  6. namespace {
  7. THashType HashList(const NUdf::TUnboxedValuePod x) {
  8. THashType hash = 0ULL;
  9. if (x.IsBoxed()) {
  10. if (const auto elements = x.GetElements()) {
  11. const auto size = x.GetListLength();
  12. for (ui32 i = 0U; i < size; ++i) {
  13. hash = CombineHashes(hash, HashDom(elements[i]));
  14. }
  15. } else {
  16. const auto it = x.GetListIterator();
  17. for (TUnboxedValue v; it.Next(v); hash = CombineHashes(hash, HashDom(v)))
  18. continue;
  19. }
  20. }
  21. return hash;
  22. }
  23. THashType HashDict(const NUdf::TUnboxedValuePod x) {
  24. THashType hash = 0ULL;
  25. if (x.IsBoxed()) {
  26. const auto it = x.GetDictIterator();
  27. for (TUnboxedValue k, v; it.NextPair(k, v);) {
  28. hash = CombineHashes(hash, CombineHashes(GetStringHash(k), HashDom(v)));
  29. }
  30. }
  31. return hash;
  32. }
  33. bool EquateLists(const NUdf::TUnboxedValuePod x, const NUdf::TUnboxedValuePod y) {
  34. if (x.IsBoxed() && y.IsBoxed()) {
  35. const auto ex = x.GetElements();
  36. const auto ey = y.GetElements();
  37. if (ex && ey) {
  38. const auto size = x.GetListLength();
  39. if (size != y.GetListLength()) {
  40. return false;
  41. }
  42. for (ui32 i = 0U; i < size; ++i) {
  43. if (!EquateDoms(ex[i], ey[i]))
  44. return false;
  45. }
  46. } else {
  47. const auto itx = x.GetListIterator();
  48. const auto ity = y.GetListIterator();
  49. for (TUnboxedValue vx, vy; itx.Next(vx);) {
  50. if (!ity.Next(vy))
  51. return false;
  52. if (!EquateDoms(vx, vy))
  53. return false;
  54. }
  55. }
  56. return true;
  57. }
  58. return x.IsBoxed() == y.IsBoxed();
  59. }
  60. bool EquateDicts(const NUdf::TUnboxedValuePod x, const NUdf::TUnboxedValuePod y) {
  61. if (x.IsBoxed() && y.IsBoxed()) {
  62. const auto size = x.GetDictLength();
  63. if (size != y.GetDictLength()) {
  64. return false;
  65. }
  66. const auto xr = static_cast<const TPair*>(x.GetResource());
  67. const auto yr = static_cast<const TPair*>(y.GetResource());
  68. // clone dict as attrnode
  69. if (xr && yr) {
  70. for (ui32 i = 0U; i < size; ++i) {
  71. if (!EquateStrings(xr[i].first, yr[i].first))
  72. return false;
  73. if (!EquateDoms(xr[i].second, yr[i].second))
  74. return false;
  75. }
  76. } else {
  77. const auto it = x.GetDictIterator();
  78. for (TUnboxedValue k, v; it.NextPair(k, v);) {
  79. if (auto l = y.Lookup(k))
  80. if (EquateDoms(v, l.GetOptionalValue()))
  81. continue;
  82. return false;
  83. }
  84. }
  85. return true;
  86. }
  87. return x.IsBoxed() == y.IsBoxed();
  88. }
  89. }
  90. THashType HashDom(const NUdf::TUnboxedValuePod x) {
  91. switch (const auto type = GetNodeType(x); type) {
  92. case ENodeType::Double:
  93. return CombineHashes(THashType(type), GetFloatHash<double>(x));
  94. case ENodeType::Uint64:
  95. return CombineHashes(THashType(type), GetIntegerHash<ui64>(x));
  96. case ENodeType::Int64:
  97. return CombineHashes(THashType(type), GetIntegerHash<i64>(x));
  98. case ENodeType::Bool:
  99. return CombineHashes(THashType(type), std::hash<bool>()(x.Get<bool>()));
  100. case ENodeType::String:
  101. return CombineHashes(THashType(type), GetStringHash(x));
  102. case ENodeType::Entity:
  103. return CombineHashes(THashType(type), THashType(~0ULL));
  104. case ENodeType::List:
  105. return CombineHashes(THashType(type), HashList(x));
  106. case ENodeType::Dict:
  107. return CombineHashes(THashType(type), HashDict(x));
  108. case ENodeType::Attr:
  109. return CombineHashes(THashType(type), CombineHashes(HashDict(x), HashDom(x.GetVariantItem().Release())));
  110. }
  111. }
  112. bool EquateDoms(const NUdf::TUnboxedValuePod x, const NUdf::TUnboxedValuePod y) {
  113. if (const auto type = GetNodeType(x); type == GetNodeType(y)) {
  114. switch (type) {
  115. case ENodeType::Double:
  116. return EquateFloats<double>(x, y);
  117. case ENodeType::Uint64:
  118. return EquateIntegers<ui64>(x, y);
  119. case ENodeType::Int64:
  120. return EquateIntegers<i64>(x, y);
  121. case ENodeType::Bool:
  122. return x.Get<bool>() == y.Get<bool>();
  123. case ENodeType::String:
  124. return EquateStrings(x, y);
  125. case ENodeType::Entity:
  126. return true;
  127. case ENodeType::List:
  128. return EquateLists(x, y);
  129. case ENodeType::Dict:
  130. return EquateDicts(x, y);
  131. case ENodeType::Attr:
  132. return EquateDicts(x, y) && EquateDoms(x.GetVariantItem().Release(), y.GetVariantItem().Release());
  133. }
  134. }
  135. return false;
  136. }
  137. }