4 template <
typename TSelf,
typename TLinkOptions,
typename TMemory,
typename TSourceTreeMethods,
5 typename TTargetTreeMethods,
typename TUnusedLinks,
typename... TBase>
11 using LinkType =
typename LinksOptionsType::LinkType;
14 static constexpr LinksConstants<LinkAddressType>
Constants = LinksOptionsType::Constants;
32 const std::size_t _memoryReservationStep;
34 std::unique_ptr<TTargetTreeMethods> _TargetsTreeMethods;
36 std::unique_ptr<TSourceTreeMethods> _SourcesTreeMethods;
38 std::unique_ptr<TUnusedLinks> _UnusedLinksListMethods;
57 return reinterpret_cast<RawLink<LinkAddressType>*
>(_links)[linkIndex];
62 auto& header = this->GetHeaderReference();
63 return header.AllocatedLinks - header.FreeLinks;
71 :
_memory(
std::move(memory)), _memoryReservationStep(memoryReservationStep)
76 void Init(TMemory& memory, std::size_t memoryReservationStep)
79 if (memory.ReservedCapacity() < memoryReservationStep)
81 memory.ReservedCapacity(memoryReservationStep);
85 auto& header = this->GetHeaderReference();
95 if (std::ranges::size(restriction) == 0)
100 auto index = restriction[
Constants.IndexPart];
101 if (std::ranges::size(restriction) == 1)
109 if (std::ranges::size(restriction) == 2)
112 auto value = restriction[1];
122 Each(restriction, [&](
const auto&) {
128 count = _SourcesTreeMethods->CountUsages(value);
130 _TargetsTreeMethods->EachUsage(value, [&](
const auto& link) {
147 auto& storedLinkValue = GetLinkReference(index);
148 if (storedLinkValue.Source == value || storedLinkValue.Target == value)
155 if (std::ranges::size(restriction) == 3)
158 auto source = restriction[
Constants.SourcePart];
159 auto target = restriction[
Constants.TargetPart];
162 if (source == any && target == any)
166 else if (source == any)
168 return _TargetsTreeMethods->CountUsages(target);
170 else if (target == any)
172 return _SourcesTreeMethods->CountUsages(source);
176 auto link = _SourcesTreeMethods->Search(source, target);
187 if (source == any && target == any)
191 auto& storedLinkValue = GetLinkReference(index);
192 if (source != any && target != any)
194 if ((storedLinkValue.Source == source) && (storedLinkValue.Target == target))
209 if ((storedLinkValue.Source == value) || (storedLinkValue.Target == value))
216 throw std::logic_error(
"Not supported exception.");
224 if (std::ranges::size(restriction) == 0)
226 for (
auto link =
LinkAddressType{1}; link <= this->GetHeaderReference().AllocatedLinks; ++link)
237 auto index = restriction[
Constants.IndexPart];
238 if (std::ranges::size(restriction) == 1)
242 return Data::Each(*
this, handler);
250 if (std::ranges::size(restriction) == 2)
252 auto value = restriction[1];
257 return Data::Each(*
this, handler);
268 if (
Each(
LinkType{index, value, any}, handler) == $break)
272 return Each(
LinkType{index, any, value}, [&](
const auto& link) {
273 return link[
Constants.SourcePart] == value ? _continue : handler(link);
286 auto& storedLinkValue = GetLinkReference(index);
287 if ((storedLinkValue.Source == value) || (storedLinkValue.Target == value))
294 if (std::ranges::size(restriction) == 3)
296 auto source = restriction[
Constants.SourcePart];
297 auto target = restriction[
Constants.TargetPart];
300 if (source == any && target == any)
302 return Data::Each(*
this, handler);
304 else if (source == any)
306 return _TargetsTreeMethods->EachUsage(target, handler);
308 else if (target == any)
310 return _SourcesTreeMethods->EachUsage(source, handler);
314 auto link = _SourcesTreeMethods->Search(source, target);
324 if (source == any && target == any)
330 auto& storedLinkValue = GetLinkReference(index);
331 if (source != any && target != any)
333 if (storedLinkValue.Source == source && storedLinkValue.Target == target)
348 if (storedLinkValue.Source == value || storedLinkValue.Target == value)
355 throw std::logic_error(
"Not supported exception.");
368 auto linkIndex = restriction[
Constants.IndexPart];
371 auto& link = GetLinkReference(linkIndex);
372 LinkType before{linkIndex, link.Source, link.Target};
375 auto& header = this->GetHeaderReference();
378 auto& firstAsSource = header.RootAsSource;
381 auto& firstAsTarget = header.RootAsTarget;
384 if (link.Source != null)
386 _SourcesTreeMethods->Detach(firstAsSource, linkIndex);
388 if (link.Target != null)
390 _TargetsTreeMethods->Detach(firstAsTarget, linkIndex);
392 link.Source = substitution[
Constants.SourcePart];
393 link.Target = substitution[
Constants.TargetPart];
394 if (link.Source != null)
396 _SourcesTreeMethods->Attach(firstAsSource, linkIndex);
398 if (link.Target != null)
400 _TargetsTreeMethods->Attach(firstAsTarget, linkIndex);
402 return handler(before,
LinkType{linkIndex, link.Source, link.Target});
409 auto* header = &this->GetHeaderReference();
410 auto freeLink = header->FirstFreeLink;
413 _UnusedLinksListMethods->Detach(freeLink);
417 auto maximumPossibleInnerReference =
Constants.InternalReferencesRange.Maximum;
418 if (header->AllocatedLinks >= maximumPossibleInnerReference)
420 throw Platform::Exceptions::LinksLimitReachedException();
422 if (header->AllocatedLinks >= (header->ReservedLinks - 1))
424 _memory.ReservedCapacity(
_memory.ReservedCapacity() + _memoryReservationStep);
426 header = &this->GetHeaderReference();
429 ++header->AllocatedLinks;
430 freeLink = header->AllocatedLinks;
439 auto& header = this->GetHeaderReference();
440 auto linkAddress = restriction[
Constants.IndexPart];
442 if (linkAddress < header.AllocatedLinks)
444 _UnusedLinksListMethods->AttachAsFirst(linkAddress);
447 else if (linkAddress == header.AllocatedLinks)
449 --header.AllocatedLinks;
453 _UnusedLinksListMethods->Detach(header.AllocatedLinks);
454 --header.AllocatedLinks;
464 auto& link = this->GetLinkReference(linkIndex);
465 return LinkType{linkIndex, link.Source, link.Target};
476 _links =
static_cast<std::byte*
>(memory.Pointer());
478 _SourcesTreeMethods = std::make_unique<TSourceTreeMethods>(_links, _header);
479 _TargetsTreeMethods = std::make_unique<TTargetTreeMethods>(_links, _header);
480 _UnusedLinksListMethods = std::make_unique<TUnusedLinks>(_links, _header);
485 if (IsExternalReference<LinkAddressType, Constants>(linkAddress))
489 return (linkAddress >=
Constants.InternalReferencesRange.Minimum) &&
490 (linkAddress <= this->GetHeaderReference().AllocatedLinks) && !
IsUnusedLink(linkAddress);
495 if (GetHeaderReference().FirstFreeLink != linkIndex)
497 auto& link = GetLinkReference(linkIndex);
Definition RawLinkDataPart.h:38