udf_string.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #pragma once
  2. #include "udf_types.h"
  3. #include "udf_allocator.h"
  4. #include "udf_string_ref.h"
  5. #include "udf_type_size_check.h"
  6. #include <util/generic/strbuf.h>
  7. #include <util/system/align.h>
  8. #include <new>
  9. namespace NYql {
  10. namespace NUdf {
  11. //////////////////////////////////////////////////////////////////////////////
  12. // TStringValue
  13. //////////////////////////////////////////////////////////////////////////////
  14. class TStringValue
  15. {
  16. friend class TUnboxedValue;
  17. friend class TUnboxedValuePod;
  18. friend class TBlockItem;
  19. friend struct TRawStringValue;
  20. class TData {
  21. friend class TStringValue;
  22. public:
  23. inline TData(ui32 size, ui64 cap)
  24. : Size_(size)
  25. , Refs_(1)
  26. , Capacity_(cap)
  27. {}
  28. inline i32 RefCount() const { return Refs_; }
  29. inline void Ref() {
  30. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 4)
  31. if (Refs_ < 0)
  32. return;
  33. #endif
  34. Refs_++;
  35. }
  36. inline void UnRef() {
  37. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 4)
  38. if (Refs_ < 0)
  39. return;
  40. #endif
  41. Y_DEBUG_ABORT_UNLESS(Refs_ > 0);
  42. if (!--Refs_) {
  43. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 8)
  44. UdfFreeWithSize(this, sizeof(*this) + Capacity_);
  45. #else
  46. UdfFree(this);
  47. #endif
  48. }
  49. }
  50. inline void ReleaseRef() {
  51. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 4)
  52. if (Refs_ < 0)
  53. return;
  54. #endif
  55. Y_DEBUG_ABORT_UNLESS(Refs_ > 0);
  56. --Refs_;
  57. }
  58. inline void DeleteUnreferenced() {
  59. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 4)
  60. if (Refs_ < 0)
  61. return;
  62. #endif
  63. if (!Refs_) {
  64. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 8)
  65. UdfFreeWithSize(this, sizeof(*this) + Capacity_);
  66. #else
  67. UdfFree(this);
  68. #endif
  69. }
  70. }
  71. inline char* Data() const { return (char*)(this+1); }
  72. inline ui32 Size() const { return Size_; }
  73. inline bool Empty() const { return Size_ == 0; }
  74. inline ui64 Capacity() const { return Capacity_; }
  75. inline i32 LockRef() noexcept {
  76. Y_DEBUG_ABORT_UNLESS(Refs_ != -1);
  77. auto ret = Refs_;
  78. Refs_ = -1;
  79. return ret;
  80. }
  81. inline void UnlockRef(i32 prev) noexcept {
  82. Y_DEBUG_ABORT_UNLESS(Refs_ == -1);
  83. Y_DEBUG_ABORT_UNLESS(prev != -1);
  84. Refs_ = prev;
  85. }
  86. private:
  87. ui32 Size_;
  88. i32 Refs_;
  89. ui64 Capacity_;
  90. };
  91. UDF_ASSERT_TYPE_SIZE(TData, 16);
  92. public:
  93. inline explicit TStringValue(ui32 size): Data_(AllocateData(size, size)) {}
  94. inline explicit TStringValue(TData* data): Data_(data) { Ref(); }
  95. inline explicit TStringValue(TStringRef data): Data_(AllocateData(data.Size(), data.Size())) {
  96. memcpy(Data_->Data(), data.Data(), data.Size());
  97. }
  98. inline TStringValue(const TStringValue& rhs): Data_(rhs.Data_) { Ref(); }
  99. inline TStringValue(TStringValue&& rhs): Data_(rhs.Data_) { rhs.Data_ = nullptr; }
  100. inline ~TStringValue() { UnRef(); }
  101. inline TStringValue& operator=(const TStringValue& rhs) {
  102. if (this != &rhs) {
  103. UnRef();
  104. Data_ = rhs.Data_;
  105. Ref();
  106. }
  107. return *this;
  108. }
  109. TStringValue& operator=(TStringValue&& rhs) {
  110. if (this != &rhs) {
  111. UnRef();
  112. Data_ = rhs.Data_;
  113. rhs.Data_ = nullptr;
  114. }
  115. return *this;
  116. }
  117. inline ui64 Capacity() const { return Data_->Capacity(); }
  118. inline ui32 Size() const { return Data_->Size(); }
  119. inline char* Data() const { return Data_->Data(); }
  120. inline ui32 size() const { return Data_->Size(); }
  121. inline char* data() const { return Data_->Data(); }
  122. inline void Ref() {
  123. if (Data_ != nullptr) {
  124. Data_->Ref();
  125. }
  126. }
  127. inline void UnRef() {
  128. if (Data_ != nullptr) {
  129. Data_->UnRef();
  130. Data_ = nullptr;
  131. }
  132. }
  133. inline void ReleaseRef() {
  134. if (Data_ != nullptr) {
  135. Data_->ReleaseRef();
  136. Data_ = nullptr;
  137. }
  138. }
  139. inline i32 RefCount() const {
  140. return Data_->RefCount();
  141. }
  142. bool TryExpandOn(ui32 len) {
  143. if (RefCount() < 0)
  144. return false;
  145. const auto size = Data_->Size_ + len;
  146. if (Data_->Capacity_ < size)
  147. return false;
  148. Data_->Size_ = size;
  149. return true;
  150. }
  151. inline i32 LockRef() noexcept {
  152. return Data_->LockRef();
  153. }
  154. inline void UnlockRef(i32 prev) noexcept {
  155. Data_->UnlockRef(prev);
  156. }
  157. private:
  158. inline TData* GetBuf() const {
  159. return Data_;
  160. }
  161. inline TData* ReleaseBuf() {
  162. if (const auto data = Data_) {
  163. Data_ = nullptr;
  164. data->ReleaseRef();
  165. return data;
  166. }
  167. return nullptr;
  168. }
  169. public:
  170. static TData* AllocateData(ui32 len, ui32 cap) {
  171. const auto alligned = AlignUp<ui64>(cap, 16ULL);
  172. const auto dataSize = sizeof(TData) + alligned;
  173. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 8)
  174. return ::new(UdfAllocateWithSize(dataSize)) TData(len, alligned);
  175. #else
  176. return ::new(UdfAllocate(dataSize)) TData(len, alligned);
  177. #endif
  178. }
  179. TData* Data_;
  180. };
  181. UDF_ASSERT_TYPE_SIZE(TStringValue, 8);
  182. } // namspace NUdf
  183. } // namspace NYql