scheme.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. #pragma once
  2. #include "scimpl_defs.h"
  3. #include "fwd.h"
  4. #include <iterator>
  5. #include <utility>
  6. namespace NSc {
  7. #ifdef _MSC_VER
  8. #pragma warning(disable : 4521 4522)
  9. #endif
  10. // todo: try to remove some rarely used methods
  11. class TValue {
  12. public:
  13. enum class EType {
  14. Null = 0 /* "Null" */,
  15. Bool /* "Bool" */,
  16. IntNumber /* "Int" */,
  17. FloatNumber /* "Float" */,
  18. String /* "String" */,
  19. Array /* "Array" */,
  20. Dict /* "Dict" */
  21. };
  22. struct TScCore;
  23. using TCorePtr = TIntrusivePtr<TScCore>;
  24. using TPoolPtr = TIntrusivePtr<NDefinitions::TPool>;
  25. using TArray = ::NSc::TArray;
  26. using TDict = ::NSc::TDict;
  27. private: // A TValue instance has only these 3 fields
  28. mutable TCorePtr TheCore; // a pointer to a refcounted (kind of) variant
  29. bool CopyOnWrite = false; // a flag that thevalue is a COW shallow copy and should produce a deep copy once modified
  30. // Thus all copies of a TValue are by default shallow. Use TValue::Clone to force a deep copy.
  31. // A COW copy will see changes in its parent, but no change in the COW copy will propagate to its parent.
  32. public:
  33. inline TValue();
  34. inline TValue(TValue& v);
  35. inline TValue(const TValue& v);
  36. inline TValue(TValue&& v) noexcept;
  37. public: // Operators
  38. inline TValue(double t);
  39. inline TValue(unsigned long long t);
  40. inline TValue(unsigned long t);
  41. inline TValue(unsigned t);
  42. inline TValue(long long t);
  43. inline TValue(long t);
  44. inline TValue(int t);
  45. // inline TValue(bool b);
  46. inline TValue(TStringBuf t);
  47. inline TValue(const char*);
  48. inline operator double() const;
  49. inline operator float() const;
  50. inline operator long long() const;
  51. inline operator long() const;
  52. inline operator int() const;
  53. inline operator short() const;
  54. inline operator char() const;
  55. inline operator unsigned long long() const;
  56. inline operator unsigned long() const;
  57. inline operator unsigned() const;
  58. inline operator unsigned short() const;
  59. inline operator unsigned char() const;
  60. inline operator signed char() const;
  61. inline operator TStringBuf() const;
  62. inline operator const ::NSc::TArray&() const;
  63. inline operator const ::NSc::TDict&() const;
  64. inline TValue& operator=(double t);
  65. inline TValue& operator=(unsigned long long t);
  66. inline TValue& operator=(unsigned long t);
  67. inline TValue& operator=(unsigned t);
  68. inline TValue& operator=(long long t);
  69. inline TValue& operator=(long t);
  70. inline TValue& operator=(int t);
  71. // inline TValue& operator=(bool t);
  72. inline TValue& operator=(TStringBuf t);
  73. inline TValue& operator=(const char* t);
  74. inline TValue& operator=(TValue& v) &;
  75. inline TValue& operator=(const TValue& v) &;
  76. inline TValue& operator=(TValue&& v) & noexcept;
  77. inline TValue& operator=(TValue& v) && = delete;
  78. inline TValue& operator=(const TValue& v) && = delete;
  79. inline TValue& operator=(TValue&& v) && = delete;
  80. public:
  81. template <class T> // ui16 or TStringBuf
  82. inline TValue& operator[](const T& idx) {
  83. return GetOrAdd(idx);
  84. }
  85. template <class T> // ui16 or TStringBuf
  86. inline const TValue& operator[](const T& idx) const {
  87. return Get(idx);
  88. }
  89. public: // Data methods ///////////////////////////////////////////////////////////
  90. inline EType GetType() const;
  91. inline bool IsNull() const;
  92. inline TValue& SetNull(); // returns self, will set type to Null
  93. TValue& Clear() {
  94. return ClearArray().ClearDict().SetNull();
  95. }
  96. public: // Number methods /////////////////////////////////////////////////////////
  97. // Bool, IntNumber and FloatNumber are all compatible.
  98. // If a TValue node has one of the types it may as well be used as another.
  99. // FloatNumber methods. Forces FloatNumber representation. Compatible with IntNumber and Bool
  100. inline bool IsNumber() const; // true if any of FloatNumber, IntNumber, Bool
  101. inline double GetNumber(double defaultval = 0) const; // Compatible with Bool, IntNumber and FloatNumber types
  102. inline double& GetNumberMutable(double defaultval = 0); // Will switch the type to FloatNumber
  103. inline TValue& SetNumber(double val = 0); // returns self, will switch the type to FloatNumber
  104. double ForceNumber(double deflt = 0) const; // Best-effort cast to double (will do TryFromString if applicable)
  105. // IntNumber methods. Forces integer representation. Compatible with FloatNumber and Bool types.
  106. // Note: if you don't care about distinguishing bools, ints and doubles, use *Number methods above
  107. inline bool IsIntNumber() const; // true only if IntNumber or Bool
  108. inline i64 GetIntNumber(i64 defaultval = 0) const; // Compatible with Bool, IntNumber and FloatNumber types
  109. inline i64& GetIntNumberMutable(i64 defaultval = 0); // Will switch the type to IntNumber
  110. inline TValue& SetIntNumber(i64 val = 0); // returns self, will switch the type to IntNumber
  111. i64 ForceIntNumber(i64 deflt = 0) const; // Best-effort cast to i64 (will do TryFromString for String)
  112. // Bool methods. Forces bool representation. Compatible with Float Number and Int Number methods above.
  113. // Note: if you don't care about distinguishing Bool, IntNumber and FloatNumber, use *Number methods above
  114. inline bool IsBool() const; // true only if Bool
  115. inline bool GetBool(bool defaultval = false) const; // Compatible with Bool, IntNumber and FloatNumber types
  116. inline TValue& SetBool(bool val = false); // returns self, will switch the type to Bool
  117. public: // Arcadia-specific boolean representation support
  118. // Tests for explicit True, also checks for arcadia-specific boolean representation
  119. bool IsTrue() const {
  120. return IsNumber() ? GetNumber() : ::IsTrue(GetString());
  121. }
  122. // Tests for explicit False, also checks for arcadia-specific boolean representation
  123. bool IsExplicitFalse() const {
  124. return IsNumber() ? !GetNumber() : IsFalse(GetString());
  125. }
  126. public: // String methods /////////////////////////////////////////////////////////
  127. inline bool IsString() const;
  128. inline TStringBuf GetString(TStringBuf defaultval = TStringBuf()) const;
  129. inline TValue& SetString(TStringBuf val = TStringBuf()); // returns self
  130. TString ForceString(const TString& deflt = TString()) const; // Best-effort cast to TString (will do ToString for numeric types)
  131. // todo: remove
  132. inline bool StringEmpty() const;
  133. inline size_t StringSize() const;
  134. public: // Array methods //////////////////////////////////////////////////////////
  135. inline bool IsArray() const;
  136. inline const TArray& GetArray() const;
  137. inline TArray& GetArrayMutable();
  138. inline TValue& SetArray(); // turns into array if needed, returns self
  139. inline TValue& ClearArray();
  140. inline bool Has(size_t idx) const;
  141. inline const TValue& Get(size_t idx) const; // returns child or default
  142. inline TValue* GetNoAdd(size_t idx); // returns link to existing child or nullptr
  143. inline TValue& Push(); // returns new child
  144. template <class T>
  145. TValue& Push(T&& t) {
  146. return Push() = std::forward<T>(t);
  147. } // returns new child
  148. TValue& Insert(ui16 idx) {
  149. return InsertUnsafe(idx);
  150. } // creates missing values, returns new child
  151. template <class T>
  152. TValue& Insert(ui16 idx, T&& v) {
  153. return InsertUnsafe(idx, std::forward<T>(v));
  154. } // creates missing values, returns new child
  155. template <class TIt>
  156. inline TValue& AppendAll(TIt begin, TIt end); // Append(vec.begin(), vec.end())
  157. template <class TColl>
  158. inline TValue& AppendAll(TColl&& coll); // Append(vec)
  159. inline TValue& AppendAll(std::initializer_list<TValue> coll);
  160. TValue& GetOrAdd(ui16 idx) {
  161. return GetOrAddUnsafe(idx);
  162. } // creates missing values, returns new child
  163. inline TValue& InsertUnsafe(size_t idx); // creates missing values, returns new child
  164. template <class T>
  165. TValue& InsertUnsafe(size_t idx, T&& t) {
  166. return InsertUnsafe(idx) = std::forward<T>(t);
  167. } // creates missing values, returns new child
  168. inline TValue& GetOrAddUnsafe(size_t idx); // creates missing values, returns new child
  169. inline TValue Pop(); // returns popped value
  170. inline TValue Delete(size_t idx); // returns deleted value if it existed, NSc::Null() otherwise
  171. inline TValue& Front() {
  172. return GetOrAdd(0);
  173. } // creates missing value, returns child
  174. inline const TValue& Front() const {
  175. return Get(0);
  176. } // returns child or default
  177. inline TValue& Back(); // creates missing value, returns child
  178. inline const TValue& Back() const; // returns child or default
  179. // todo: remove
  180. inline bool ArrayEmpty() const;
  181. inline size_t ArraySize() const;
  182. public: // Dict methods
  183. inline bool IsDict() const;
  184. inline const TDict& GetDict() const;
  185. inline TDict& GetDictMutable();
  186. inline TValue& SetDict(); // turns into dict if not one, returns self
  187. inline TValue& ClearDict();
  188. inline bool Has(TStringBuf idx) const;
  189. inline const TValue& Get(TStringBuf idx) const;
  190. inline TValue* GetNoAdd(TStringBuf idx); // returns link to existing child or nullptr
  191. TValue& Add(TStringBuf idx) {
  192. return GetOrAdd(idx);
  193. }
  194. template <class T>
  195. TValue& Add(TStringBuf idx, T&& t) {
  196. return Add(idx) = std::forward<T>(t);
  197. }
  198. inline TValue& GetOrAdd(TStringBuf idx); // creates missing value, returns child
  199. inline TValue Delete(TStringBuf idx); // returns deleted value
  200. inline TValue& AddAll(std::initializer_list<std::pair<TStringBuf, TValue>> t);
  201. TStringBufs DictKeys(bool sorted = true) const;
  202. TStringBufs& DictKeys(TStringBufs&, bool sorted = true) const;
  203. // todo: remove
  204. inline bool DictEmpty() const;
  205. inline size_t DictSize() const;
  206. public: // Json methods ////////////////////////////////////////////////
  207. using TJsonOpts = NSc::TJsonOpts;
  208. using EJsonOpts = TJsonOpts::EJsonOpts;
  209. static const EJsonOpts JO_DEFAULT = TJsonOpts::JO_DEFAULT;
  210. static const EJsonOpts JO_SORT_KEYS = TJsonOpts::JO_SORT_KEYS;
  211. static const EJsonOpts JO_SKIP_UNSAFE = TJsonOpts::JO_SKIP_UNSAFE; // skip non-utf8 strings
  212. static const EJsonOpts JO_PRETTY = TJsonOpts::JO_PRETTY;
  213. static const EJsonOpts JO_SAFE = TJsonOpts::JO_SAFE; // JO_SORT_KEYS | JO_SKIP_UNSAFE
  214. static const EJsonOpts JO_PARSER_STRICT_WITH_COMMENTS = TJsonOpts::JO_PARSER_STRICT_WITH_COMMENTS; // strict json + strict utf8
  215. static const EJsonOpts JO_PARSER_STRICT = TJsonOpts::JO_PARSER_STRICT; // strict json + strict utf8 + comments are disallowed
  216. static const EJsonOpts JO_PARSER_DISALLOW_DUPLICATE_KEYS = TJsonOpts::JO_PARSER_DISALLOW_DUPLICATE_KEYS;
  217. static TValue FromJson(TStringBuf, const TJsonOpts& = TJsonOpts());
  218. static TValue FromJsonThrow(TStringBuf, const TJsonOpts& = TJsonOpts());
  219. static bool FromJson(TValue&, TStringBuf, const TJsonOpts& = TJsonOpts());
  220. // TODO: Переименовать ToJson в ToJsonUnsafe, а ToJsonSafe в ToJson
  221. TString ToJson(const TJsonOpts& = TJsonOpts()) const;
  222. const TValue& ToJson(IOutputStream&, const TJsonOpts& = TJsonOpts()) const; // returns self
  223. // ToJson(JO_SORT_KEYS | JO_SKIP_UNSAFE)
  224. TString ToJsonSafe(const TJsonOpts& = TJsonOpts()) const;
  225. const TValue& ToJsonSafe(IOutputStream&, const TJsonOpts& = TJsonOpts()) const;
  226. // ToJson(JO_SORT_KEYS | JO_PRETTY | JO_SKIP_UNSAFE)
  227. TString ToJsonPretty(const TJsonOpts& = TJsonOpts()) const;
  228. const TValue& ToJsonPretty(IOutputStream&, const TJsonOpts& = TJsonOpts()) const;
  229. NJson::TJsonValue ToJsonValue() const;
  230. static TValue FromJsonValue(const NJson::TJsonValue&);
  231. static TValue& FromJsonValue(TValue&, const NJson::TJsonValue&); // returns self
  232. static TJsonOpts MakeOptsSafeForSerializer(TJsonOpts = TJsonOpts());
  233. static TJsonOpts MakeOptsPrettyForSerializer(TJsonOpts = TJsonOpts());
  234. public: // Merge methods ////////////////////////////////////////////////
  235. /*
  236. * LHS.MergeUpdate(RHS):
  237. * 1. Dict <- Dict:
  238. * - Copy all nonconflicting key-value pairs from RHS to LHS.
  239. * - For every pair of conflicting values apply LHS[key].MergeUpdate(RHS[key]).
  240. * 2. Anything <- Null:
  241. * - Do nothing.
  242. * 3. Other conflicts:
  243. * - Copy RHS over LHS.
  244. *
  245. * LHS.ReverseMerge(RHS):
  246. * 1. Dict <- Dict:
  247. * - Copy all nonconflicting key-value pairs from RHS to LHS.
  248. * - For every pair of conflicting values apply LHS[key].ReverseMerge(RHS[key]).
  249. * 2. Null <- Anything:
  250. * - Copy RHS over LHS.
  251. * 3. Other conflicts:
  252. * - Do nothing.
  253. */
  254. TValue& MergeUpdateJson(TStringBuf json); // returns self
  255. TValue& ReverseMergeJson(TStringBuf json); // returns self
  256. static bool MergeUpdateJson(TValue&, TStringBuf json); // returns true unless failed to parse the json
  257. static bool ReverseMergeJson(TValue&, TStringBuf json); // returns true unless failed to parse the json
  258. TValue& MergeUpdate(const TValue& delta); // return self
  259. TValue& ReverseMerge(const TValue& delta); // return self
  260. public: // Path methods /////////////////////////////////////////////////////////
  261. // TODO: add throwing variants
  262. // make sure to properly escape the tokens
  263. static TString EscapeForPath(TStringBuf rawKey); // converts a raw dict key into a valid token for a selector path
  264. static bool PathValid(TStringBuf path); // returns true if the path is syntactically valid
  265. bool PathExists(TStringBuf path) const; // returns true if the path is syntactically valid and the target value exists
  266. const TValue& TrySelect(TStringBuf path) const; // returns the target value
  267. // if the path is syntactically valid and the target value exists
  268. // otherwise returns NSc::Null()
  269. TValue* TrySelectOrAdd(TStringBuf path); // returns the target value if it exists or creates if not
  270. // if the path is syntactically valid
  271. // otherwise returns NSc::Null()
  272. TValue TrySelectAndDelete(TStringBuf path); // deletes and returns the target value
  273. // if the path is syntactically valid and the target value existed
  274. // otherwise returns NSc::Null()
  275. public: // Copy methods /////////////////////////////////////////////////////////
  276. TValue Clone() const; // returns deep copy of self (on the separate pool)
  277. TValue& CopyFrom(const TValue& other); // deep copy other value into self, returns self
  278. TValue& Swap(TValue& v);
  279. static bool Same(const TValue&, const TValue&); // point to the same core
  280. static bool Equal(const TValue&, const TValue&); // recursively equal
  281. static bool SamePool(const TValue&, const TValue&); // share arena
  282. public:
  283. // very specific methods useful in very specific corner cases
  284. static TValue From(const ::google::protobuf::Message&, bool mapAsDict = false);
  285. void To(::google::protobuf::Message&, const TProtoOpts& opts = {}) const;
  286. public:
  287. inline explicit TValue(TPoolPtr&);
  288. static const TScCore& DefaultCore();
  289. static const TArray& DefaultArray();
  290. static const TDict& DefaultDict();
  291. static const TValue& DefaultValue();
  292. static const TValue& Null() {
  293. return DefaultValue();
  294. }
  295. void DoWriteJsonImpl(IOutputStream&, const TJsonOpts&, NImpl::TKeySortContext&, NImpl::TSelfLoopContext&) const;
  296. bool IsSameOrAncestorOf(const TValue& other) const;
  297. private:
  298. TValue& DoMerge(const TValue& delta, bool olddelta);
  299. TValue& DoMergeImpl(const TValue& delta, bool olddelta, NImpl::TSelfLoopContext&, NImpl::TSelfOverrideContext&);
  300. TValue& DoCopyFromImpl(const TValue& other, NImpl::TSelfLoopContext&, NImpl::TSelfOverrideContext&);
  301. NJson::TJsonValue ToJsonValueImpl(NImpl::TSelfLoopContext&) const;
  302. bool IsSameOrAncestorOfImpl(const TScCore& other, NImpl::TSelfLoopContext& loopCtx) const;
  303. inline TScCore& CoreMutable();
  304. inline TScCore& CoreMutableForSet();
  305. inline const TScCore& Core() const;
  306. static inline TScCore* NewCore(TPoolPtr&);
  307. static TValue FromField(const ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*);
  308. static TValue FromRepeatedField(const ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, int index);
  309. void ValueToField(const TValue& value, ::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
  310. void ToField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
  311. void ToEnumField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
  312. void ToRepeatedField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
  313. void ToMapField(::google::protobuf::Message&, const ::google::protobuf::FieldDescriptor*, const TProtoOpts& opts) const;
  314. };
  315. inline const TValue& Null() {
  316. return TValue::DefaultValue();
  317. }
  318. class TArray: public TDeque<TValue, TPoolAllocator>, TNonCopyable {
  319. using TParent = TDeque<TValue, TPoolAllocator>;
  320. public:
  321. TArray(TMemoryPool* p)
  322. : TParent(p)
  323. {
  324. }
  325. template <class TIt>
  326. void AppendAll(TIt begin, TIt end) {
  327. TParent::insert(TParent::end(), begin, end);
  328. }
  329. template <class TColl>
  330. void AppendAll(TColl&& coll) {
  331. AppendAll(std::begin(coll), std::end(coll));
  332. }
  333. void AppendAll(std::initializer_list<TValue> coll) {
  334. AppendAll(coll.begin(), coll.end());
  335. }
  336. const TValue& operator[](size_t i) const {
  337. return EnsureIndex(i);
  338. }
  339. TValue& operator[](size_t i) {
  340. return EnsureIndex(i);
  341. }
  342. const TValue& front() const {
  343. return EnsureIndex(0);
  344. }
  345. TValue& front() {
  346. return EnsureIndex(0);
  347. }
  348. const TValue& back() const {
  349. return EnsureIndex(LastIndex());
  350. }
  351. TValue& back() {
  352. return EnsureIndex(LastIndex());
  353. }
  354. void pop_back() {
  355. if (empty())
  356. return;
  357. TParent::pop_back();
  358. }
  359. void pop_front() {
  360. if (empty())
  361. return;
  362. TParent::pop_front();
  363. }
  364. private:
  365. size_t LastIndex() const {
  366. return ::Max<size_t>(size(), 1) - 1;
  367. }
  368. TValue& EnsureIndex(size_t i) {
  369. if (i >= size())
  370. resize(::Min<size_t>(i + 1, ::Max<ui16>()), TValue::DefaultValue());
  371. return TParent::operator[](i);
  372. }
  373. const TValue& EnsureIndex(size_t i) const {
  374. return i < size() ? TParent::operator[](i) : TValue::DefaultValue();
  375. }
  376. };
  377. // todo: densehashtable
  378. // todo: allow insertions
  379. // todo: make TDict methods safe
  380. class TDict: public THashMap<TStringBuf, TValue, THash<TStringBuf>, TEqualTo<TStringBuf>, TPoolAllocator>, TNonCopyable {
  381. using TParent = THashMap<TStringBuf, TValue, THash<TStringBuf>, TEqualTo<TStringBuf>, TPoolAllocator>;
  382. public:
  383. TDict(TMemoryPool* p)
  384. : TParent(p)
  385. {
  386. }
  387. template <class TStr>
  388. const TValue& Get(const TStr& key) const {
  389. const_iterator it = find(key);
  390. return it != end() ? it->second : TValue::DefaultValue();
  391. }
  392. };
  393. }
  394. #include "scimpl.h"
  395. #include "scheme_cast.h"
  396. #ifdef _MSC_VER
  397. #pragma warning(default : 4521 4522)
  398. #endif