3 template <
typename TStorage>
4 static void RunRandomCreations(TStorage& storage,
typename TStorage::LinkAddressType amountOfCreations)
7 using namespace Platform::Random;
8 using namespace Platform::Ranges;
9 auto& randomGenerator64 = Random::RandomHelpers::Default;
10 for (
typename TStorage::LinkAddressType i{0}; i < amountOfCreations; ++i)
12 Range<typename TStorage::LinkAddressType> linksAddressRange{0, Count(storage)};
13 auto source = Random::NextUInt64(randomGenerator64, linksAddressRange);
14 auto target = Random::NextUInt64(randomGenerator64, linksAddressRange);
19 template <
typename TStorage>
20 static void RunRandomSearches(
const TStorage& storage,
typename TStorage::LinkAddressType amountOfSearches)
23 using namespace Platform::Random;
24 using namespace Platform::Ranges;
25 auto randomGenerator64 = Random::RandomHelpers::Default;
26 for (
typename TStorage::LinkAddressType i{0}; i < amountOfSearches; ++i)
28 auto linksAddressRange = Range<typename TStorage::LinkAddressType>(0, Count(storage));
29 auto source = Random::NextUInt64(randomGenerator64, linksAddressRange);
30 auto target = Random::NextUInt64(randomGenerator64, linksAddressRange);
35 template <
typename TStorage>
36 static void RunRandomDeletions(TStorage& storage,
typename TStorage::LinkAddressType amountOfDeletions)
39 using namespace Platform::Random;
40 using namespace Platform::Ranges;
41 auto& randomGenerator64 = RandomHelpers::Default;
42 auto linksCount = Count(storage);
43 typename TStorage::LinkAddressType min = amountOfDeletions > linksCount ? 0 : linksCount - amountOfDeletions;
44 for (
typename TStorage::LinkAddressType i{0}; i < amountOfDeletions; ++i)
46 linksCount = Count(storage);
47 if (linksCount <= min)
51 auto linksAddressRange = Range<typename TStorage::LinkAddressType>(min, linksCount);
52 auto linkAddress = Random::NextUInt64(randomGenerator64, linksAddressRange);
53 Delete(storage, linkAddress);
57 template <
typename TStorage>
59 typename TStorage::LinkAddressType maximumOperationsPerCycle)
61 using namespace Platform::Random;
62 using namespace Platform::Ranges;
63 using namespace Platform::Interfaces;
64 for (
auto N = 1; N < maximumOperationsPerCycle; N++)
66 auto& randomGen64 = RandomHelpers::Default;
67 typename TStorage::LinkAddressType created = 0;
68 typename TStorage::LinkAddressType deleted = 0;
69 for (
auto i = 0; i < N; i++)
71 auto linksCount = Count(storage);
72 auto createPoint = Random::NextBoolean(randomGen64);
73 if (linksCount >= 2 && createPoint)
75 Ranges::Range linksAddressRange{1, linksCount};
76 auto source = Random::NextUInt64(randomGen64, linksAddressRange);
77 auto target = Random::NextUInt64(randomGen64, linksAddressRange);
78 auto resultLink =
GetOrCreate(storage, source, target);
79 if (resultLink > linksCount)
90 auto count = Count(storage);
91 for (
auto i = 0; i < count; i++)
95 DIRECT_METHOD_CALL(TStorage, storage,
Update, link, 0, 0);
96 Delete(storage, link);
103 template <
typename TStorage>
104 static typename TStorage::LinkAddressType Delete(TStorage& storage,
typename TStorage::LinkAddressType linkToDelete,
105 const typename TStorage::WriteHandlerType& handler)
107 if (Exists(storage, linkToDelete))
109 EnforceResetValues(storage, linkToDelete, handler);
111 return Delete(storage, linkToDelete, handler);
114 template <
typename TStorage>
115 static typename TStorage::LinkAddressType First(
const TStorage& storage)
117 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
118 auto $break{constants.Break};
119 typename TStorage::LinkAddressType firstLink = 0;
120 Expects(constants.Null != firstLink);
122 TStorage, storage, Each,
123 typename TStorage::LinkType{storage.Constants.Any, storage.Constants.Any, storage.Constants.Any},
124 [&firstLink, $break](
const typename TStorage::LinkType& link) {
128 Ensures(constants.Null != firstLink);
132 template <
typename TStorage>
133 static typename TStorage::HandlerParameterType SingleOrDefault(
const TStorage& storage,
134 const typename TStorage::LinkType& query)
136 typename TStorage::LinkType result{};
138 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
139 auto linkHandler{[&result, &count, &constants](
const typename TStorage::LinkType& link) {
144 return constants.Continue;
149 return constants.Break;
152 DIRECT_METHOD_CALL(TStorage, storage, Each, query, linkHandler);
156 template <
typename TStorage>
157 static bool CheckPathExistence(
const TStorage& storage,
158 std::convertible_to<typename TStorage::LinkAddressType>
auto... pathPack)
160 typename TStorage::HandlerParameterType path{
static_cast<typename TStorage::LinkdAddressType
>(pathPack)...};
161 auto current = path[0];
162 if (!Exists(storage, current))
166 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
167 for (
typename TStorage::LinkAddressType i{1}; i < std::ranges::size(path); ++i)
170 auto values = GetLink(storage, current);
171 auto source = GetSource(storage, values);
172 auto target = GetTarget(storage, values);
173 if (target == source && next == source)
177 if ((source != next) && (target != next))
186 template <
typename TStorage>
187 static typename TStorage::LinkAddressType GetByKeys(
188 TStorage& storage,
typename TStorage::LinkAddressType root,
189 std::convertible_to<typename TStorage::LinkAddressType>
auto... pathPack)
191 typename TStorage::HandlerParameterType path{
static_cast<typename TStorage::LinkdAddressType
>(pathPack)...};
192 storage.EnsureLinkExists(root,
"root");
193 auto currentLink = root;
194 for (
typename TStorage::LinkAddressType i{0}; i < std::ranges::size(path); ++i)
196 currentLink = GetLink(storage, currentLink)[path[i]];
201 template <
typename TStorage>
202 static auto GetIndex(
const TStorage& storage,
const typename TStorage::LinkType& link)
204 return link[storage.Constants.IndexPart];
207 template <
typename TStorage>
208 static typename TStorage::LinkAddressType GetSource(
const TStorage& storage,
209 typename TStorage::LinkAddressType linkAddress)
211 return GetLink(storage, linkAddress)[storage.Constants.SourcePart];
214 template <
typename TStorage>
215 static typename TStorage::LinkAddressType GetSource(
const TStorage& storage,
216 const typename TStorage::LinkType& link)
218 return link[storage.Constants.SourcePart];
221 template <
typename TStorage>
222 static typename TStorage::LinkAddressType GetTarget(
const TStorage& storage,
223 typename TStorage::LinkAddressType linkAddress)
225 return GetLink(storage, linkAddress)[storage.Constants.TargetPart];
228 template <
typename TStorage>
229 static typename TStorage::LinkAddressType GetTarget(
const TStorage& storage,
230 const typename TStorage::LinkType& link)
232 return link[storage.Constants.TargetPart];
235 template <
typename TStorage>
236 static std::vector<typename TStorage::LinkType> All(
const TStorage& storage,
237 const typename TStorage::LinkType& restriction)
239 using namespace Platform::Collections;
240 auto $continue{storage.Constants.Continue};
241 std::vector<typename TStorage::LinkType> allLinks{};
242 DIRECT_METHOD_CALL(TStorage, storage, Each, restriction,
243 [&allLinks, $continue](
const typename TStorage::LinkType& link) {
244 allLinks.push_back(link);
250 template <
typename TStorage>
251 static auto All(
const TStorage& storage)
253 return All(storage,
typename TStorage::LinkType{});
256 template <
typename TStorage,
typename... TRestrictions>
257 requires(
sizeof...(TRestrictions) > 0 &&
258 (std::convertible_to<TRestrictions, typename TStorage::LinkAddressType> && ...))
259 static auto All(
const TStorage& storage, TRestrictions... restrictionPack)
261 typename TStorage::LinkType restriction{
static_cast<typename TStorage::LinkAddressType
>(restrictionPack)...};
262 return All(storage, restriction);
265 template <
typename TStorage>
266 static typename TStorage::LinkAddressType AllIndices(TStorage& storage,
267 const typename TStorage::LinkType& restriction)
269 std::vector<typename TStorage::LinkType> allIndices{};
270 auto usages = std::vector<typename TStorage::LinkType>();
271 auto $continue = storage.Constants.Continue;
272 DIRECT_METHOD_CALL(TStorage, storage, Each, restriction,
273 [&allIndices, $continue](
const typename TStorage::LinkType& link) {
274 allIndices.push_back(link);
280 template <
typename TStorage>
281 static void EnsureLinkExists(TStorage& storage,
const typename TStorage::LinkType& restriction)
283 for (
auto i{0}; i < restriction.Count(); ++i)
285 if (!storage.Exists(restriction[i]))
287 throw ArgumentLinkDoesNotExistsException<typename TStorage::LinkAddressType>(
289 std::string(
"sequence[").append(Platform::Converters::To<std::string>(i)).append(1,
']'));
294 template <
typename TStorage>
295 static bool Exists(TStorage& storage,
typename TStorage::LinkAddressType source,
296 typename TStorage::LinkAddressType target)
298 return DIRECT_METHOD_CALL(TStorage, storage, Count,
299 typename TStorage::LinkType{storage.Constants.Any, source, target}) > 0;
302 template <
typename TStorage>
303 static void EnsureInnerReferenceExists(TStorage& storage,
typename TStorage::LinkAddressType reference,
304 std::string argumentName)
306 using namespace Platform::Exceptions;
307 if (storage.Constants.IsInternalReference(reference) && !storage.Exists(reference))
309 throw ArgumentLinkDoesNotExistsException<typename TStorage::LinkAddressType>(reference, argumentName);
313 template <
typename TStorage>
314 static void EnsureInnerReferenceExists(TStorage& storage,
const typename TStorage::LinkType& restriction,
315 std::string argumentName)
317 using namespace Platform::Exceptions;
318 for (std::int32_t i = 0; i < restriction.Count(); ++i)
320 storage.EnsureInnerReferenceExists(restriction[i], argumentName);
324 template <
typename TStorage>
325 static void EnsureLinkIsAnyOrExists(TStorage& storage,
const typename TStorage::LinkType& restriction)
327 using namespace Platform::Exceptions;
328 auto any = storage.Constants.Any;
329 for (
auto i{0}; i < restriction.Count(); ++i)
331 if ((any != restriction[i]) && !storage.Exists(restriction[i]))
333 throw ArgumentLinkDoesNotExistsException<typename TStorage::LinkAddressType>(
335 std::string(
"sequence[").append(Platform::Converters::To<std::string>(i)).append(1,
']'));
340 template <
typename TStorage>
341 static void EnsureLinkIsAnyOrExists(TStorage& storage,
typename TStorage::LinkAddressType linkAddress,
342 std::string argumentName)
344 using namespace Platform::Exceptions;
345 if ((storage.Constants.Any != linkAddress) && !storage.Exists(linkAddress))
347 throw ArgumentLinkDoesNotExistsException<typename TStorage::LinkAddressType>(linkAddress, argumentName);
351 template <
typename TStorage>
352 static void EnsureLinkIsItselfOrExists(TStorage& storage,
typename TStorage::LinkAddressType linkAddress,
353 std::string argumentName)
355 using namespace Platform::Exceptions;
356 if ((storage.Constants.Itself != linkAddress) && !storage.Exists(linkAddress))
358 throw ArgumentLinkDoesNotExistsException<typename TStorage::LinkAddressType>(linkAddress, argumentName);
362 template <
typename TStorage>
363 static void EnsureDoesNotExists(TStorage& storage,
typename TStorage::LinkAddressType source,
364 typename TStorage::LinkAddressType target)
366 using namespace Platform::Exceptions;
367 if (storage.Exists(source, target))
369 throw Platform::Exceptions::LinkWithSameValueAlreadyExistsException();
373 template <
typename TStorage>
374 static void EnsureNoUsages(TStorage& storage,
typename TStorage::LinkAddressType linkAddress)
376 using namespace Platform::Exceptions;
377 if (storage.HasUsages(linkAddress))
379 throw ArgumentLinkHasDependenciesException<typename TStorage::LinkAddressType>(linkAddress);
383 template <
typename TStorage>
384 static void EnsureCreated(TStorage& storage, std::function<
typename TStorage::LinkAddressType()> creator,
385 const typename TStorage::LinkType& addresses)
387 using Address =
typename TStorage::LinkAddressType;
388 std::unordered_set<Address> remaining;
389 for (
auto address : addresses)
391 if (address != storage.Constants.Null && address <= storage.Constants.InternalReferencesRange.Maximum &&
392 !Platform::Data::Exists(storage, address))
394 remaining.insert(address);
397 const auto requested = remaining;
398 std::unordered_set<Address> created;
401 while (!remaining.empty())
403 auto address = creator();
404 if (address == storage.Constants.Null || !created.insert(address).second)
406 throw std::runtime_error(
"The creator did not allocate a new link");
408 remaining.erase(address);
410 for (
auto address : created)
412 if (!requested.contains(address))
414 Platform::Data::Update(
415 storage,
typename TStorage::LinkType{address},
416 typename TStorage::LinkType{address, storage.Constants.Null, storage.Constants.Null});
417 Platform::Data::Delete(storage, address);
422 template <
typename TStorage>
423 static void EnsureCreated(TStorage& storage,
const typename TStorage::LinkType& addresses)
425 EnsureCreated(storage, std::function<
typename TStorage::LinkAddressType()>{[&storage] {
426 return Platform::Data::Create(storage);
431 template <
typename TStorage>
432 static void EnsurePointsCreated(TStorage& storage,
const typename TStorage::LinkType& addresses)
434 EnsureCreated(storage, std::function<
typename TStorage::LinkAddressType()>{[&storage] {
435 auto point = Platform::Data::Create(storage);
436 return Platform::Data::Update(storage,
typename TStorage::LinkType{point},
437 typename TStorage::LinkType{point, point, point});
442 template <
typename TStorage>
443 static typename TStorage::LinkAddressType CountUsages(TStorage& storage,
444 typename TStorage::LinkAddressType linkAddress)
446 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
447 auto values = GetLink(storage, linkAddress);
448 auto usagesAsSource = DIRECT_METHOD_CALL(
449 TStorage, storage, Count,
typename TStorage::LinkType{constants.Any, storage, linkAddress, constants.Any});
450 if (linkAddress == GetSource(storage, values))
454 auto usagesAsTarget = DIRECT_METHOD_CALL(
455 TStorage, storage, Count,
typename TStorage::LinkType{constants.Any, storage, constants.Any, linkAddress});
456 if (linkAddress == GetTarget(storage, values))
460 return usagesAsSource + usagesAsTarget;
463 template <
typename TStorage>
464 static bool HasUsages(TStorage& storage,
typename TStorage::LinkAddressType linkAddress)
466 return CountUsages(storage, linkAddress) > 0;
469 template <
typename TStorage>
470 typename TStorage::LinkAddressType
SearchOrDefault(TStorage& storage,
typename TStorage::LinkAddressType source,
471 typename TStorage::LinkAddressType target)
473 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
474 auto _break = constants.Break;
475 typename TStorage::LinkAddressType searchedLinkAddress{};
476 DIRECT_METHOD_CALL(TStorage, storage, Each,
typename TStorage::LinkType{storage.Constants.Any, source, target},
477 [&searchedLinkAddress, _break](
const typename TStorage::LinkType& link) {
478 searchedLinkAddress = link[0];
481 return searchedLinkAddress;
483 template <
typename TStorage>
486 auto point = Platform::Data::Create(storage);
487 return Update(storage, point, point, point);
490 template <
typename TStorage>
491 static typename TStorage::LinkAddressType
CreatePoint(TStorage& storage,
492 const typename TStorage::WriteHandlerType& handler)
494 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
495 WriteHandlerState<TStorage> handlerState{constants.Continue, constants.Break, handler};
496 typename TStorage::LinkAddressType linkAddress;
497 typename TStorage::LinkAddressType HandlerWrapper = [&linkAddress,
498 &handlerState](
const typename TStorage::LinkType& before,
499 const typename TStorage::LinkType& after) {
500 linkAddress = after[0];
501 return handlerState.Handle(before, after);
504 DIRECT_METHOD_CALL(TStorage, storage, Create,
typename TStorage::LinkType{}, HandlerWrapper));
505 return handlerState.Apply(
506 DIRECT_METHOD_CALL(TStorage, storage,
Update, linkAddress, linkAddress, linkAddress, HandlerWrapper));
509 template <
typename TStorage>
510 typename TStorage::LinkAddressType
CreateAndUpdate(TStorage& storage,
typename TStorage::LinkAddressType source,
511 typename TStorage::LinkAddressType target)
513 auto $continue{storage.Constants.Continue};
514 typename TStorage::LinkAddressType linkAddress;
516 storage, source, target,
517 [&linkAddress, $continue](
const typename TStorage::LinkType&,
const typename TStorage::LinkType& after) {
518 linkAddress = after[0];
523 template <
typename TStorage>
524 static typename TStorage::LinkAddressType
CreateAndUpdate(TStorage& storage,
525 typename TStorage::LinkAddressType source,
526 typename TStorage::LinkAddressType target,
527 const typename TStorage::WriteHandlerType& handler)
529 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
530 typename TStorage::LinkAddressType createdLinkAddress;
531 WriteHandlerState<TStorage> handlerState{constants.Continue, constants.Break, handler};
533 DIRECT_METHOD_CALL(TStorage, storage, Create,
typename TStorage::LinkType{},
534 [&createdLinkAddress, &handlerState](
const typename TStorage::LinkType& before,
535 const typename TStorage::LinkType& after) {
536 createdLinkAddress = after[0];
537 return handlerState.Handle(before, after);
539 return handlerState.Apply(
Update(storage, createdLinkAddress, source, target, handlerState.Handler));
542 template <
typename TStorage>
543 typename TStorage::LinkAddressType
Update(TStorage& storage,
544 CArray<typename TStorage::LinkAddressType>
auto&& restriction,
545 CArray<typename TStorage::LinkAddressType>
auto&& substitution)
547 auto $continue{storage.Constants.Continue};
548 typename TStorage::LinkAddressType updatedLinkAddress;
549 DIRECT_METHOD_CALL(TStorage, storage,
Update, restriction, substitution,
550 [&updatedLinkAddress, $continue](
const typename TStorage::LinkType&,
551 const typename TStorage::LinkType& after) {
552 updatedLinkAddress = after[0];
555 return updatedLinkAddress;
558 template <
typename TStorage>
559 static typename TStorage::LinkAddressType
Update(TStorage& storage,
const typename TStorage::LinkType& restriction,
560 const typename TStorage::WriteHandlerType& handler)
562 const auto length{std::ranges::size(restriction)};
565 return MergeAndDelete(storage, restriction[0], restriction[1], handler);
567 else if (length == 4)
569 return UpdateOrCreateOrGet(storage, restriction[0], restriction[1], restriction[2], restriction[3],
574 return Update(storage, restriction[0], restriction[1], restriction[2], handler);
578 template <
typename TStorage>
579 static typename TStorage::LinkAddressType
Update(TStorage& storage,
typename TStorage::LinkAddressType linkAddress,
580 typename TStorage::LinkAddressType newSource,
581 typename TStorage::LinkAddressType newTarget,
582 const typename TStorage::WriteHandlerType& handler)
584 return DIRECT_METHOD_CALL(TStorage, storage,
Update,
typename TStorage::LinkType{linkAddress},
585 typename TStorage::LinkType{linkAddress, newSource, newTarget}, handler);
599 template <
typename TStorage>
600 static typename TStorage::LinkAddressType
Update(TStorage& storage,
typename TStorage::LinkAddressType linkAddress,
601 typename TStorage::LinkAddressType newSource,
602 typename TStorage::LinkAddressType newTarget)
604 auto $continue{storage.Constants.Continue};
605 typename TStorage::LinkAddressType updatedLinkAddress;
606 Update(storage, linkAddress, newSource, newTarget,
607 [&updatedLinkAddress, $continue](
const typename TStorage::LinkType&,
608 const typename TStorage::LinkType& after) {
609 updatedLinkAddress = after[0];
612 return updatedLinkAddress;
615 template <
typename TStorage>
616 static typename TStorage::LinkAddressType
Update(TStorage& storage,
const typename TStorage::LinkType& restriction)
618 auto $continue{storage.Constants.Continue};
619 typename TStorage::LinkAddressType updatedLinkAddress;
620 return Update(storage, restriction,
621 [&updatedLinkAddress, $continue](
const typename TStorage::LinkType&,
622 const typename TStorage::LinkType& after) {
623 updatedLinkAddress = after;
628 template <
typename TStorage>
629 static typename TStorage::LinkAddressType
Update(
630 TStorage& storage,
const typename TStorage::WriteHandlerType& handler,
631 std::convertible_to<typename TStorage::LinkAddressType>
auto... restrictionPack)
633 typename TStorage::HandlerParameterType restriction{
634 static_cast<typename TStorage::HandlerParameterType
>(restrictionPack)...};
635 return Update(storage, restriction, handler);
638 template <
typename TStorage>
639 static typename TStorage::LinkType ResolveConstantAsSelfReference(
const TStorage& storage,
640 typename TStorage::LinkAddressType constant,
641 const typename TStorage::LinkType& restriction,
642 const typename TStorage::LinkType& substitution)
644 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
645 auto restrictionIndex = GetIndex(storage, restriction);
646 auto substitutionIndex = GetIndex(storage, substitution);
647 if (constants.Null == substitutionIndex)
649 substitutionIndex = restrictionIndex;
651 auto source = GetSource(storage, substitution);
652 auto target = GetTarget(storage, substitution);
653 source = constant == source ? substitutionIndex : source;
654 target = constant == target ? substitutionIndex : target;
655 return typename TStorage::LinkType{substitutionIndex, source, target};
658 template <
typename TStorage>
659 typename TStorage::LinkAddressType
GetOrCreate(TStorage& storage,
typename TStorage::LinkAddressType source,
660 typename TStorage::LinkAddressType target)
662 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
664 if (link == constants.Null)
671 template <
typename TStorage>
672 static typename TStorage::LinkAddressType UpdateOrCreateOrGet(TStorage& storage,
673 typename TStorage::LinkAddressType source,
674 typename TStorage::LinkAddressType target,
675 typename TStorage::LinkAddressType newSource,
676 typename TStorage::LinkAddressType newTarget,
677 const typename TStorage::WriteHandlerType& handler)
680 if (storage.Constants.Null == link)
684 if ((source == newSource) && (target == newTarget))
688 return Update(storage, link, newSource, newTarget, handler);
691 template <
typename TStorage>
692 static typename TStorage::LinkAddressType UpdateOrCreateOrGet(TStorage& storage,
693 typename TStorage::LinkAddressType source,
694 typename TStorage::LinkAddressType target,
695 typename TStorage::LinkAddressType newSource,
696 typename TStorage::LinkAddressType newTarget)
698 auto $continue = storage.Constants.Continue;
699 typename TStorage::LinkAddressType resultLink;
701 storage, source, target, newSource, newTarget,
702 [&resultLink, $continue](
const typename TStorage::LinkType&,
const typename TStorage::LinkType& after) {
703 resultLink = after[0];
709 template <
typename TStorage>
710 typename TStorage::LinkAddressType
DeleteIfExists(TStorage& storage,
typename TStorage::LinkAddressType source,
711 typename TStorage::LinkAddressType target)
713 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
714 auto linkAddress = storage.SearchOrDefault(source, target);
715 if (linkAddress != constants.Null)
717 return Delete(storage, linkAddress);
719 return constants.Null;
722 template <
typename TStorage>
723 static void DeleteMany(TStorage& storage,
const typename TStorage::LinkType& linkAddressesToDelete)
725 for (
auto linkAddress : linkAddressesToDelete)
727 Delete(storage, linkAddress);
731 template <
typename TStorage>
732 static typename TStorage::LinkAddressType DeleteAllUsages(TStorage& storage,
733 typename TStorage::LinkAddressType linkIndex,
734 const typename TStorage::WriteHandlerType& handler)
736 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
737 auto any = constants.Any;
738 auto $continue = storage.Constants.Continue;
739 auto $break = storage.Constants.Break;
740 auto usagesAsSourceQuery =
typename TStorage::LinkType{any, linkIndex, any};
741 auto usagesAsTargetQuery =
typename TStorage::LinkType{any, any, linkIndex};
742 auto usages = std::vector<typename TStorage::LinkType>();
743 DIRECT_METHOD_CALL(TStorage, storage, Each, usagesAsSourceQuery,
744 [&usages, $continue](
const typename TStorage::LinkType& link) {
745 usages.push_back(link);
748 DIRECT_METHOD_CALL(TStorage, storage, Each, usagesAsTargetQuery, [&usages, $continue](
auto&& link) {
749 usages.push_back(link);
752 WriteHandlerState<TStorage> handlerState{$continue, $break, handler};
753 for (
auto usage : usages)
755 auto usageAddress{GetIndex(storage, usage)};
756 if (linkIndex == usageAddress || Exists(storage, usageAddress))
760 auto result = DIRECT_METHOD_CALL(TStorage, storage, Delete, usage, handlerState.Handler);
761 handlerState.Apply(result);
763 return handlerState.Result;
766 template <
typename TStorage>
767 static void DeleteAllUsages(TStorage& storage,
typename TStorage::LinkAddressType linkIndex)
769 DeleteAllUsages(storage, linkIndex,
nullptr);
772 template <
typename TStorage>
775 auto handler = [](
typename TStorage::LinkType,
typename TStorage::LinkType) {
776 return typename TStorage::LinkAddressType{};
778 auto any = storage.Constants.Any;
779 for (
auto count = Count(storage); count != storage.Constants.Null; count = Count(storage))
781 DIRECT_METHOD_CALL(TStorage, storage, Delete, {count, any, any}, handler);
785 template <
typename TStorage>
786 static bool AreValuesReset(
const TStorage& storage,
typename TStorage::LinkAddressType linkIndex)
788 auto nullConstant = storage.Constants.Null;
789 auto link = GetLink(storage, linkIndex);
790 for (std::size_t i = 1; i < std::ranges::size(link); ++i)
792 if (nullConstant != link[i])
800 template <
typename TStorage>
801 typename TStorage::LinkAddressType
ResetValues(TStorage& storage,
typename TStorage::LinkAddressType linkAddress,
802 const typename TStorage::WriteHandlerType& handler)
804 return Update(storage, linkAddress, 0, 0, handler);
807 template <
typename TStorage>
808 void ResetValues(TStorage& storage,
typename TStorage::LinkAddressType linkAddress)
810 auto $break = storage.Constants.Break;
814 template <
typename TStorage>
815 static typename TStorage::LinkAddressType EnforceResetValues(TStorage& storage,
816 typename TStorage::LinkAddressType linkIndex,
817 const typename TStorage::WriteHandlerType& handler)
819 if (!AreValuesReset(storage, linkIndex))
823 return storage.Constants.Continue;
826 template <
typename TStorage>
827 static typename TStorage::LinkAddressType EnforceResetValues(TStorage& storage,
828 typename TStorage::LinkAddressType linkIndex)
830 return EnforceResetValues(storage, linkIndex,
nullptr);
833 template <
typename TStorage>
834 static typename TStorage::LinkAddressType MergeUsages(TStorage& storage,
835 typename TStorage::LinkAddressType oldLinkIndex,
836 typename TStorage::LinkAddressType newLinkIndex,
837 const typename TStorage::WriteHandlerType& handler)
839 if (newLinkIndex == oldLinkIndex)
843 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
844 auto usagesAsSource = All(storage,
typename TStorage::LinkType(constants.Any, oldLinkIndex, constants.Any));
845 WriteHandlerState<TStorage> handlerState{constants.Continue, constants.Break, handler};
846 for (
auto i{0}; i < std::ranges::size(usagesAsSource); ++i)
848 auto usageAsSource = usagesAsSource[i];
849 if (oldLinkIndex == GetIndex(storage, usageAsSource))
853 typename TStorage::LinkType restriction{GetIndex(storage, usageAsSource)};
854 typename TStorage::LinkType substitution = (newLinkIndex, GetTarget(storage, usageAsSource));
856 DIRECT_METHOD_CALL(TStorage, storage,
Update, restriction, substitution, handlerState.Handler));
858 auto usagesAsTarget = All(storage,
typename TStorage::LinkType(constants.Any, constants.Any, oldLinkIndex));
859 for (
auto i{0}; i < std::ranges::size(usagesAsTarget); ++i)
861 auto usageAsTarget = usagesAsTarget[i];
862 if (oldLinkIndex == GetIndex(storage, usageAsTarget))
866 auto substitution =
typename TStorage::LinkType(GetTarget(storage, usageAsTarget), newLinkIndex);
868 DIRECT_METHOD_CALL(TStorage, storage,
Update, usageAsTarget, substitution, handlerState.Handler));
870 return handlerState.Result;
873 template <
typename TStorage>
874 static void MergeUsages(TStorage& storage,
typename TStorage::LinkAddressType oldLinkIndex,
875 typename TStorage::LinkAddressType newLinkIndex)
877 MergeUsages(storage, oldLinkIndex, newLinkIndex,
nullptr);
880 template <
typename TStorage>
881 static typename TStorage::LinkAddressType MergeAndDelete(TStorage& storage,
882 typename TStorage::LinkAddressType oldLinkIndex,
883 typename TStorage::LinkAddressType newLinkIndex)
885 if (newLinkIndex != oldLinkIndex)
887 MergeUsages(storage, oldLinkIndex, newLinkIndex);
888 Delete(storage, oldLinkIndex);
893 template <
typename TStorage>
894 static typename TStorage::LinkAddressType MergeAndDelete(TStorage& storage,
895 typename TStorage::LinkAddressType oldLinkIndex,
896 typename TStorage::LinkAddressType newLinkIndex,
897 const typename TStorage::WriteHandlerType& handler)
899 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
900 WriteHandlerState<TStorage> handlerState{constants.Continue, constants.Break, handler};
901 if (newLinkIndex != oldLinkIndex)
903 handlerState.Apply(MergeUsages(storage, oldLinkIndex, newLinkIndex, handlerState.Handler));
904 handlerState.Apply(Delete(storage, oldLinkIndex, handlerState.Handler));
906 return handlerState.Result;
909 template <
typename TStorage>
910 static std::string Format(TStorage& storage,
const typename TStorage::LinkType& link)
912 constexpr auto constants = std::remove_cvref_t<
decltype(storage)>::Constants;
915 .append(std::to_string(GetIndex(storage, link)))
918 .append(std::to_string(GetSource(storage, link)))
922 .append(std::to_string(GetTarget(storage, link)))
926 template <
typename TStorage>
927 std::string Format(TStorage& storage,
typename TStorage::LinkAddressType linkAddress)
929 return Format(GetLink(storage, linkAddress));
932 template <
typename TStorage>
933 typename TStorage::LinkAddressType HasUsages(TStorage& storage,
typename TStorage::LinkAddressType linkAddress)
935 return storage.CountUsages(linkAddress) != 0;
938 template <
typename TStorage>
939 static void DeleteByQuery(TStorage& storage,
typename TStorage::LinkType query)
941 typename TStorage::LinkType queryResult;
942 DIRECT_METHOD_CALL(TStorage, storage, Each, query,
943 [&](
typename TStorage::LinkType vec) ->
typename TStorage::LinkAddressType {
944 queryResult.push_back(vec[storage.Constants.IndexPart]);
945 return storage.Constants.Continue;
948 for (
auto link : queryResult)
950 Delete(storage, link);