scheme.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. #include "scheme.h"
  2. #include "scimpl_private.h"
  3. #include <util/generic/algorithm.h>
  4. #include <util/string/cast.h>
  5. namespace NSc {
  6. TStringBufs& TValue::DictKeys(TStringBufs& vs, bool sorted) const {
  7. if (!IsDict()) {
  8. return vs;
  9. }
  10. const ::NSc::TDict& dict = GetDict();
  11. vs.reserve(vs.size() + dict.size());
  12. for (const auto& it : dict)
  13. vs.push_back(it.first);
  14. if (sorted) {
  15. Sort(vs.begin(), vs.end());
  16. }
  17. return vs;
  18. }
  19. TStringBufs TValue::DictKeys(bool sorted) const {
  20. TStringBufs bufs;
  21. DictKeys(bufs, sorted);
  22. return bufs;
  23. }
  24. TValue& TValue::MergeUpdate(const TValue& delta, TMaybe<TMergeOptions> mergeOptions) {
  25. return DoMerge(delta, false, mergeOptions);
  26. }
  27. TValue& TValue::ReverseMerge(const TValue& delta, TMaybe<TMergeOptions> mergeOptions) {
  28. return DoMerge(delta, true, mergeOptions);
  29. }
  30. TValue& TValue::MergeUpdateJson(TStringBuf data, TMaybe<TMergeOptions> mergeOptions) {
  31. return MergeUpdate(FromJson(data), mergeOptions);
  32. }
  33. TValue& TValue::ReverseMergeJson(TStringBuf data, TMaybe<TMergeOptions> mergeOptions) {
  34. return ReverseMerge(FromJson(data), mergeOptions);
  35. }
  36. bool TValue::MergeUpdateJson(TValue& v, TStringBuf data, TMaybe<TMergeOptions> mergeOptions) {
  37. NSc::TValue m;
  38. if (!FromJson(m, data)) {
  39. return false;
  40. }
  41. v.MergeUpdate(m, mergeOptions);
  42. return true;
  43. }
  44. bool TValue::ReverseMergeJson(TValue& v, TStringBuf data, TMaybe<TMergeOptions> mergeOptions) {
  45. NSc::TValue m;
  46. if (!FromJson(m, data)) {
  47. return false;
  48. }
  49. v.ReverseMerge(m, mergeOptions);
  50. return true;
  51. }
  52. TValue TValue::Clone() const {
  53. return TValue().CopyFrom(*this);
  54. }
  55. TValue TValue::CreateNew() const {
  56. return Y_LIKELY(TheCore) ? TValue(TheCore->Pool) : TValue();
  57. }
  58. double TValue::ForceNumber(double deflt) const {
  59. const TScCore& core = Core();
  60. if (core.IsNumber()) {
  61. return core.GetNumber(deflt);
  62. }
  63. if (TStringBuf str = core.GetString(TStringBuf())) {
  64. {
  65. double result = 0;
  66. if (TryFromString<double>(str, result)) {
  67. return result;
  68. }
  69. }
  70. {
  71. i64 result = 0;
  72. if (TryFromString<i64>(str, result)) {
  73. return result;
  74. }
  75. }
  76. {
  77. ui64 result = 0;
  78. if (TryFromString<ui64>(str, result)) {
  79. return result;
  80. }
  81. }
  82. }
  83. return deflt;
  84. }
  85. i64 TValue::ForceIntNumber(i64 deflt) const {
  86. const TScCore& core = Core();
  87. if (core.IsNumber()) {
  88. return core.GetIntNumber(deflt);
  89. }
  90. if (TStringBuf str = core.GetString(TStringBuf())) {
  91. {
  92. i64 result = 0;
  93. if (TryFromString<i64>(str, result)) {
  94. return result;
  95. }
  96. }
  97. {
  98. ui64 result = 0;
  99. if (TryFromString<ui64>(str, result)) {
  100. return result;
  101. }
  102. }
  103. {
  104. double result = 0;
  105. if (TryFromString<double>(str, result)) {
  106. return result;
  107. }
  108. }
  109. }
  110. return deflt;
  111. }
  112. TString TValue::ForceString(const TString& deflt) const {
  113. const TScCore& core = Core();
  114. if (core.IsString()) {
  115. return ToString(core.GetString(TStringBuf()));
  116. }
  117. if (core.IsIntNumber()) {
  118. return ToString(core.GetIntNumber(0));
  119. }
  120. if (core.IsNumber()) {
  121. return ToString(core.GetNumber(0));
  122. }
  123. return deflt;
  124. }
  125. TValue& /*this*/ TValue::CopyFrom(const TValue& other) {
  126. if (Same(*this, other)) {
  127. return *this;
  128. }
  129. using namespace NImpl;
  130. return DoCopyFromImpl(other, GetTlsInstance<TSelfLoopContext>(), GetTlsInstance<TSelfOverrideContext>());
  131. }
  132. TValue& TValue::DoCopyFromImpl(const TValue& other,
  133. NImpl::TSelfLoopContext& otherLoopCtx,
  134. NImpl::TSelfOverrideContext& selfOverrideCtx) {
  135. if (Same(*this, other)) {
  136. return *this;
  137. }
  138. CoreMutableForSet(); // trigger COW
  139. TScCore& selfCore = *TheCore;
  140. const TScCore& otherCore = other.Core();
  141. NImpl::TSelfLoopContext::TGuard loopCheck(otherLoopCtx, otherCore);
  142. NImpl::TSelfOverrideContext::TGuard overrideGuard(selfOverrideCtx, selfCore);
  143. selfCore.SetNull();
  144. if (!loopCheck.Ok) {
  145. return *this; // a loop encountered (and asserted), skip the back reference
  146. }
  147. switch (otherCore.ValueType) {
  148. default:
  149. Y_ASSERT(false);
  150. [[fallthrough]];
  151. case EType::Null:
  152. break;
  153. case EType::Bool:
  154. selfCore.SetBool(otherCore.IntNumber);
  155. break;
  156. case EType::IntNumber:
  157. selfCore.SetIntNumber(otherCore.IntNumber);
  158. break;
  159. case EType::FloatNumber:
  160. selfCore.SetNumber(otherCore.FloatNumber);
  161. break;
  162. case EType::String:
  163. if (selfCore.Pool.Get() == otherCore.Pool.Get()) {
  164. selfCore.SetOwnedString(otherCore.String);
  165. } else {
  166. selfCore.SetString(otherCore.String);
  167. }
  168. break;
  169. case EType::Array:
  170. selfCore.SetArray();
  171. for (const TValue& e : otherCore.GetArray()) {
  172. selfCore.Push().DoCopyFromImpl(e, otherLoopCtx, selfOverrideCtx);
  173. }
  174. break;
  175. case EType::Dict: {
  176. TCorePtr tmp = NewCore(selfCore.Pool);
  177. auto& tmpCore = *tmp;
  178. tmpCore.SetDict();
  179. const TDict& d = otherCore.GetDict();
  180. tmpCore.Dict.reserve(d.size());
  181. for (const TDict::value_type& e : d) {
  182. tmpCore.Add(e.first).DoCopyFromImpl(e.second, otherLoopCtx, selfOverrideCtx);
  183. }
  184. TheCore = std::move(tmp);
  185. break;
  186. }
  187. }
  188. return *this;
  189. }
  190. TValue& TValue::Swap(TValue& v) {
  191. DoSwap(TheCore, v.TheCore);
  192. DoSwap(CopyOnWrite, v.CopyOnWrite);
  193. return *this;
  194. }
  195. bool TValue::Same(const TValue& a, const TValue& b) {
  196. return a.TheCore.Get() == b.TheCore.Get();
  197. }
  198. bool TValue::SamePool(const TValue& a, const TValue& b) {
  199. return Same(a, b) || (a.TheCore && b.TheCore && a.TheCore->Pool.Get() == b.TheCore->Pool.Get());
  200. }
  201. bool TValue::Equal(const TValue& a, const TValue& b) {
  202. if (Same(a, b)) {
  203. return true;
  204. }
  205. const NSc::TValue::TScCore& coreA = a.Core();
  206. const NSc::TValue::TScCore& coreB = b.Core();
  207. if (coreA.IsNumber() && coreB.IsNumber()) {
  208. return coreA.GetIntNumber(0) == coreB.GetIntNumber(0) && coreA.GetNumber(0) == coreB.GetNumber(0);
  209. }
  210. if (coreA.ValueType != coreB.ValueType) {
  211. return false;
  212. }
  213. if (coreA.IsString()) {
  214. std::string_view strA = coreA.String;
  215. std::string_view strB = coreB.String;
  216. if (strA != strB) {
  217. return false;
  218. }
  219. } else if (coreA.IsArray()) {
  220. const TArray& arrA = coreA.Array;
  221. const TArray& arrB = coreB.Array;
  222. if (arrA.size() != arrB.size()) {
  223. return false;
  224. }
  225. for (size_t i = 0; i < arrA.size(); ++i) {
  226. if (!Equal(arrA[i], arrB[i])) {
  227. return false;
  228. }
  229. }
  230. } else if (coreA.IsDict()) {
  231. const ::NSc::TDict& dictA = coreA.Dict;
  232. const ::NSc::TDict& dictB = coreB.Dict;
  233. if (dictA.size() != dictB.size()) {
  234. return false;
  235. }
  236. for (const auto& ita : dictA) {
  237. ::NSc::TDict::const_iterator itb = dictB.find(ita.first);
  238. if (itb == dictB.end() || !Equal(ita.second, itb->second)) {
  239. return false;
  240. }
  241. }
  242. }
  243. return true;
  244. }
  245. TValue& TValue::DoMerge(const TValue& delta, bool lowPriorityDelta, TMaybe<TMergeOptions> mergeOptions) {
  246. if (Same(*this, delta)) {
  247. return *this;
  248. }
  249. using namespace NImpl;
  250. return DoMergeImpl(delta, lowPriorityDelta, mergeOptions, GetTlsInstance<TSelfLoopContext>(), GetTlsInstance<TSelfOverrideContext>());
  251. }
  252. TValue& TValue::DoMergeImpl(const TValue& delta, bool lowPriorityDelta, TMaybe<TMergeOptions> mergeOptions,
  253. NImpl::TSelfLoopContext& otherLoopCtx,
  254. NImpl::TSelfOverrideContext& selfOverrideGuard) {
  255. if (Same(*this, delta)) {
  256. return *this;
  257. }
  258. bool allowMergeArray = mergeOptions.Defined() && mergeOptions->ArrayMergeMode == TMergeOptions::EArrayMergeMode::Merge;
  259. if (delta.IsDict() && (!lowPriorityDelta || IsDict() || IsNull())) {
  260. TScCore& core = CoreMutable();
  261. const TScCore& deltaCore = delta.Core();
  262. NImpl::TSelfLoopContext::TGuard loopCheck(otherLoopCtx, deltaCore);
  263. if (!loopCheck.Ok) {
  264. return *this; // a loop encountered (and asserted), skip the back reference
  265. }
  266. if (!lowPriorityDelta || IsNull()) {
  267. SetDict();
  268. }
  269. const TDict& ddelta = deltaCore.Dict;
  270. for (const auto& dit : ddelta) {
  271. core.GetOrAdd(dit.first).DoMergeImpl(dit.second, lowPriorityDelta, mergeOptions, otherLoopCtx, selfOverrideGuard);
  272. }
  273. } else if (delta.IsArray() && allowMergeArray && (!lowPriorityDelta || IsArray() || IsNull())) {
  274. TScCore& core = CoreMutable();
  275. const TScCore& deltaCore = delta.Core();
  276. NImpl::TSelfLoopContext::TGuard loopCheck(otherLoopCtx, deltaCore);
  277. if (!loopCheck.Ok) {
  278. return *this; // a loop encountered (and asserted), skip the back reference
  279. }
  280. if (!lowPriorityDelta || IsNull()) {
  281. SetArray();
  282. }
  283. Y_ASSERT(IsArray());
  284. const TArray& adelta = deltaCore.Array;
  285. if (adelta.size() > core.Array.size()) {
  286. core.Array.resize(adelta.size());
  287. }
  288. for (size_t i = 0; i < adelta.size(); ++i) {
  289. core.Array[i].DoMergeImpl(adelta[i], lowPriorityDelta, mergeOptions, otherLoopCtx, selfOverrideGuard);
  290. }
  291. } else if (!delta.IsNull() && (!lowPriorityDelta || IsNull())) {
  292. DoCopyFromImpl(delta, otherLoopCtx, selfOverrideGuard);
  293. }
  294. return *this;
  295. }
  296. NJson::TJsonValue TValue::ToJsonValue() const {
  297. using namespace NImpl;
  298. return ToJsonValueImpl(GetTlsInstance<TSelfLoopContext>());
  299. }
  300. NJson::TJsonValue TValue::ToJsonValueImpl(NImpl::TSelfLoopContext& loopCtx) const {
  301. const TScCore& core = Core();
  302. switch (core.ValueType) {
  303. default:
  304. case EType::Null:
  305. return NJson::TJsonValue(NJson::JSON_NULL);
  306. case EType::Bool:
  307. return NJson::TJsonValue(core.GetBool());
  308. case EType::IntNumber:
  309. return NJson::TJsonValue(core.GetIntNumber());
  310. case EType::FloatNumber:
  311. return NJson::TJsonValue(core.GetNumber());
  312. case EType::String:
  313. return NJson::TJsonValue(core.String);
  314. case EType::Array: {
  315. NImpl::TSelfLoopContext::TGuard loopGuard(loopCtx, core);
  316. if (!loopGuard.Ok) {
  317. return NJson::TJsonValue(NJson::JSON_NULL);
  318. }
  319. NJson::TJsonValue result(NJson::JSON_ARRAY);
  320. const TArray& arr = core.Array;
  321. for (const auto& item : arr) {
  322. result.AppendValue(NJson::TJsonValue::UNDEFINED) = item.ToJsonValueImpl(loopCtx);
  323. }
  324. return result;
  325. }
  326. case EType::Dict: {
  327. NImpl::TSelfLoopContext::TGuard loopGuard(loopCtx, core);
  328. if (!loopGuard.Ok) {
  329. return NJson::TJsonValue(NJson::JSON_NULL);
  330. }
  331. NJson::TJsonValue result(NJson::JSON_MAP);
  332. const TDict& dict = core.Dict;
  333. for (const auto& item : dict) {
  334. result.InsertValue(item.first, NJson::TJsonValue::UNDEFINED) = item.second.ToJsonValueImpl(loopCtx);
  335. }
  336. return result;
  337. }
  338. }
  339. }
  340. TValue TValue::FromJsonValue(const NJson::TJsonValue& val) {
  341. TValue result;
  342. FromJsonValue(result, val);
  343. return result;
  344. }
  345. TValue& TValue::FromJsonValue(TValue& res, const NJson::TJsonValue& val) {
  346. TScCore& core = res.CoreMutableForSet();
  347. core.SetNull();
  348. switch (val.GetType()) {
  349. default:
  350. case NJson::JSON_UNDEFINED:
  351. case NJson::JSON_NULL:
  352. break;
  353. case NJson::JSON_BOOLEAN:
  354. core.SetBool(val.GetBoolean());
  355. break;
  356. case NJson::JSON_INTEGER:
  357. core.SetIntNumber(val.GetInteger());
  358. break;
  359. case NJson::JSON_UINTEGER:
  360. core.SetIntNumber(val.GetUInteger());
  361. break;
  362. case NJson::JSON_DOUBLE:
  363. core.SetNumber(val.GetDouble());
  364. break;
  365. case NJson::JSON_STRING:
  366. core.SetString(val.GetString());
  367. break;
  368. case NJson::JSON_ARRAY: {
  369. core.SetArray();
  370. for (const auto& item : val.GetArray()) {
  371. FromJsonValue(core.Push(), item);
  372. }
  373. break;
  374. }
  375. case NJson::JSON_MAP: {
  376. core.SetDict();
  377. for (const auto& item : val.GetMap()) {
  378. FromJsonValue(core.Add(item.first), item.second);
  379. }
  380. break;
  381. }
  382. }
  383. return res;
  384. }
  385. struct TDefaults {
  386. TValue::TPoolPtr Pool = MakeIntrusive<NDefinitions::TPool>();
  387. TValue::TScCore Core{Pool};
  388. };
  389. const TValue::TScCore& TValue::DefaultCore() {
  390. return Default<TDefaults>().Core;
  391. }
  392. const TArray& TValue::DefaultArray() {
  393. return Default<TDefaults>().Core.Array;
  394. }
  395. const TDict& TValue::DefaultDict() {
  396. return Default<TDefaults>().Core.Dict;
  397. }
  398. const TValue& TValue::DefaultValue() {
  399. return *FastTlsSingleton<TValue>();
  400. }
  401. bool TValue::IsSameOrAncestorOf(const TValue& other) const {
  402. using namespace NImpl;
  403. return IsSameOrAncestorOfImpl(other.Core(), GetTlsInstance<TSelfLoopContext>());
  404. }
  405. bool TValue::IsSameOrAncestorOfImpl(const TScCore& other, NImpl::TSelfLoopContext& loopCtx) const {
  406. const TScCore& core = Core();
  407. if (&core == &other) {
  408. return true;
  409. }
  410. switch (core.ValueType) {
  411. default:
  412. return false;
  413. case EType::Array: {
  414. NImpl::TSelfLoopContext::TGuard loopGuard(loopCtx, core);
  415. if (!loopGuard.Ok) {
  416. return false;
  417. }
  418. for (const auto& item : core.Array) {
  419. if (item.IsSameOrAncestorOfImpl(other, loopCtx)) {
  420. return true;
  421. }
  422. }
  423. return false;
  424. }
  425. case EType::Dict: {
  426. NImpl::TSelfLoopContext::TGuard loopGuard(loopCtx, core);
  427. if (!loopGuard.Ok) {
  428. return false;
  429. }
  430. for (const auto& item : core.Dict) {
  431. if (item.second.IsSameOrAncestorOfImpl(other, loopCtx)) {
  432. return true;
  433. }
  434. }
  435. return false;
  436. }
  437. }
  438. }
  439. namespace NPrivate {
  440. int CompareStr(const NSc::TValue& a, TStringBuf b) {
  441. return a.GetString().compare(b);
  442. }
  443. int CompareInt(const NSc::TValue& a, i64 r) {
  444. i64 l = a.GetIntNumber();
  445. return l < r ? -1 : l > r ? 1 : 0;
  446. }
  447. int CompareFloat(const NSc::TValue& a, double r) {
  448. double l = a.GetNumber();
  449. return l < r ? -1 : l > r ? 1 : 0;
  450. }
  451. }
  452. bool operator==(const NSc::TValue& a, const NSc::TValue& b) {
  453. return NSc::TValue::Equal(a, b);
  454. }
  455. bool operator!=(const NSc::TValue& a, const NSc::TValue& b) {
  456. return !NSc::TValue::Equal(a, b);
  457. }
  458. #define LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(T, Impl) \
  459. bool operator==(const NSc::TValue& a, T b) { \
  460. return NPrivate::Impl(a, b) == 0; \
  461. } \
  462. bool operator==(T b, const NSc::TValue& a) { \
  463. return NPrivate::Impl(a, b) == 0; \
  464. } \
  465. bool operator!=(const NSc::TValue& a, T b) { \
  466. return NPrivate::Impl(a, b) != 0; \
  467. } \
  468. bool operator!=(T b, const NSc::TValue& a) { \
  469. return NPrivate::Impl(a, b) != 0; \
  470. } \
  471. bool operator<=(const NSc::TValue& a, T b) { \
  472. return NPrivate::Impl(a, b) <= 0; \
  473. } \
  474. bool operator<=(T b, const NSc::TValue& a) { \
  475. return NPrivate::Impl(a, b) >= 0; \
  476. } \
  477. bool operator>=(const NSc::TValue& a, T b) { \
  478. return NPrivate::Impl(a, b) >= 0; \
  479. } \
  480. bool operator>=(T b, const NSc::TValue& a) { \
  481. return NPrivate::Impl(a, b) <= 0; \
  482. } \
  483. bool operator<(const NSc::TValue& a, T b) { \
  484. return NPrivate::Impl(a, b) < 0; \
  485. } \
  486. bool operator<(T b, const NSc::TValue& a) { \
  487. return NPrivate::Impl(a, b) > 0; \
  488. } \
  489. bool operator>(const NSc::TValue& a, T b) { \
  490. return NPrivate::Impl(a, b) > 0; \
  491. } \
  492. bool operator>(T b, const NSc::TValue& a) { \
  493. return NPrivate::Impl(a, b) < 0; \
  494. }
  495. #define LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(T) \
  496. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(signed T, CompareInt) \
  497. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(unsigned T, CompareInt)
  498. //LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(bool, CompareInt)
  499. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(char, CompareInt)
  500. LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(char)
  501. LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(short)
  502. LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(int)
  503. LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(long)
  504. LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL(long long)
  505. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(float, CompareFloat)
  506. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(double, CompareFloat)
  507. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(TStringBuf, CompareStr)
  508. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(const TString&, CompareStr)
  509. LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL(const char* const, CompareStr)
  510. #undef LIBRARY_SCHEME_DECLARE_TVALUE_OPS_IMPL
  511. #undef LIBRARY_SCHEME_DECLARE_TVALUE_INT_OPS_IMPL
  512. }
  513. template <>
  514. void Out<NSc::TValue>(IOutputStream& o, TTypeTraits<NSc::TValue>::TFuncParam v) {
  515. o.Write(v.ToJson(true));
  516. }