1//! @file register_data_structure.hpp
2//! @author ryftchen
3//! @brief The declarations (register_data_structure) in the application module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#pragma once
8
9#ifndef _PRECOMPILED_HEADER
10#include <bitset>
11#include <functional>
12#else
13#include "application/pch/precompiled_header.hpp"
14#endif
15
16#include "utility/include/common.hpp"
17#include "utility/include/macro.hpp"
18#include "utility/include/reflection.hpp"
19
20//! @brief The application module.
21namespace application // NOLINT(modernize-concat-nested-namespaces)
22{
23//! @brief Data-structure-registering-related functions in the application module.
24namespace reg_ds
25{
26extern const char* version() noexcept;
27
28//! @brief Represent the maximum value of an enum.
29//! @tparam Enum - type of specific enum
30template <typename Enum>
31struct Bottom;
32
33//! @brief Enumerate specific cache instances.
34enum class CacheInstance : std::uint8_t
35{
36 //! @brief First in first out.
37 firstInFirstOut,
38 //! @brief Least frequently used.
39 leastFrequentlyUsed,
40 //! @brief Least recently used.
41 leastRecentlyUsed
42};
43//! @brief Store the maximum value of the CacheInstance enum.
44template <>
45struct Bottom<CacheInstance>
46{
47 //! @brief Maximum value of the CacheInstance enum.
48 static constexpr std::uint8_t value{3};
49};
50
51//! @brief Enumerate specific filter instances.
52enum class FilterInstance : std::uint8_t
53{
54 //! @brief Bloom.
55 bloom,
56 //! @brief Quotient.
57 quotient
58};
59//! @brief Store the maximum value of the FilterInstance enum.
60template <>
61struct Bottom<FilterInstance>
62{
63 //! @brief Maximum value of the FilterInstance enum.
64 static constexpr std::uint8_t value{2};
65};
66
67//! @brief Enumerate specific graph instances.
68enum class GraphInstance : std::uint8_t
69{
70 //! @brief Undirected.
71 undirected,
72 //! @brief Directed.
73 directed
74};
75//! @brief Store the maximum value of the GraphInstance enum.
76template <>
77struct Bottom<GraphInstance>
78{
79 //! @brief Maximum value of the GraphInstance enum.
80 static constexpr std::uint8_t value{2};
81};
82
83//! @brief Enumerate specific heap instances.
84enum class HeapInstance : std::uint8_t
85{
86 //! @brief Binary.
87 binary,
88 //! @brief Leftist.
89 leftist,
90 //! @brief Skew.
91 skew
92};
93//! @brief Store the maximum value of the HeapInstance enum.
94template <>
95struct Bottom<HeapInstance>
96{
97 //! @brief Maximum value of the HeapInstance enum.
98 static constexpr std::uint8_t value{3};
99};
100
101//! @brief Enumerate specific linear instances.
102enum class LinearInstance : std::uint8_t
103{
104 //! @brief Doubly linked list.
105 doublyLinkedList,
106 //! @brief Stack.
107 stack,
108 //! @brief Queue.
109 queue
110};
111//! @brief Store the maximum value of the LinearInstance enum.
112template <>
113struct Bottom<LinearInstance>
114{
115 //! @brief Maximum value of the LinearInstance enum.
116 static constexpr std::uint8_t value{3};
117};
118
119//! @brief Enumerate specific tree instances.
120enum class TreeInstance : std::uint8_t
121{
122 //! @brief Binary search.
123 binarySearch,
124 //! @brief Adelson-Velsky-Landis.
125 adelsonVelskyLandis,
126 //! @brief Splay.
127 splay
128};
129//! @brief Store the maximum value of the TreeInstance enum.
130template <>
131struct Bottom<TreeInstance>
132{
133 //! @brief Maximum value of the TreeInstance enum.
134 static constexpr std::uint8_t value{3};
135};
136
137//! @brief Manage data structure choices.
138class ApplyDataStructure
139{
140public:
141 //! @brief Enumerate specific data structure choices.
142 enum class Category : std::uint8_t
143 {
144 //! @brief Cache.
145 cache,
146 //! @brief Filter.
147 filter,
148 //! @brief Graph.
149 graph,
150 //! @brief Heap.
151 heap,
152 //! @brief Linear.
153 linear,
154 //! @brief Tree.
155 tree
156 };
157
158 //! @brief Bit flags for managing cache instances.
159 std::bitset<Bottom<CacheInstance>::value> cacheOpts;
160 //! @brief Bit flags for managing filter instances.
161 std::bitset<Bottom<FilterInstance>::value> filterOpts;
162 //! @brief Bit flags for managing graph instances.
163 std::bitset<Bottom<GraphInstance>::value> graphOpts;
164 //! @brief Bit flags for managing heap instances.
165 std::bitset<Bottom<HeapInstance>::value> heapOpts;
166 //! @brief Bit flags for managing linear instances.
167 std::bitset<Bottom<LinearInstance>::value> linearOpts;
168 //! @brief Bit flags for managing tree instances.
169 std::bitset<Bottom<TreeInstance>::value> treeOpts;
170};
171
172//! @brief Manage the data structure choices.
173namespace manage
174{
175extern ApplyDataStructure& choiceApplier();
176
177extern bool present();
178extern void clear();
179} // namespace manage
180
181//! @brief Constraint for data-structure-registering.
182//! @tparam Inst - type of instance
183template <typename Inst>
184concept Registrant =
185 std::is_same_v<Inst, CacheInstance> || std::is_same_v<Inst, FilterInstance> || std::is_same_v<Inst, GraphInstance>
186 || std::is_same_v<Inst, HeapInstance> || std::is_same_v<Inst, LinearInstance> || std::is_same_v<Inst, TreeInstance>;
187//! @brief Set the choice.
188//! @tparam Inst - type of target instance
189//! @param choice - target choice
190template <typename Inst>
191requires Registrant<Inst>
192void setChoice(const std::string& choice);
193//! @brief Run the candidates.
194//! @tparam Inst - type of target instance
195//! @param candidates - container for the candidate target choices
196template <typename Inst>
197requires Registrant<Inst>
198void runCandidates(const std::vector<std::string>& candidates);
199
200//! @brief Register cache.
201namespace cache
202{
203extern const char* version() noexcept;
204} // namespace cache
205template <>
206void setChoice<CacheInstance>(const std::string& choice);
207template <>
208void runCandidates<CacheInstance>(const std::vector<std::string>& candidates);
209
210//! @brief Register filter.
211namespace filter
212{
213extern const char* version() noexcept;
214} // namespace filter
215template <>
216void setChoice<FilterInstance>(const std::string& choice);
217template <>
218void runCandidates<FilterInstance>(const std::vector<std::string>& candidates);
219
220//! @brief Register graph.
221namespace graph
222{
223extern const char* version() noexcept;
224} // namespace graph
225template <>
226void setChoice<GraphInstance>(const std::string& choice);
227template <>
228void runCandidates<GraphInstance>(const std::vector<std::string>& candidates);
229
230//! @brief Register heap.
231namespace heap
232{
233extern const char* version() noexcept;
234} // namespace heap
235template <>
236void setChoice<HeapInstance>(const std::string& choice);
237template <>
238void runCandidates<HeapInstance>(const std::vector<std::string>& candidates);
239
240//! @brief Register linear.
241namespace linear
242{
243extern const char* version() noexcept;
244} // namespace linear
245template <>
246void setChoice<LinearInstance>(const std::string& choice);
247template <>
248void runCandidates<LinearInstance>(const std::vector<std::string>& candidates);
249
250//! @brief Register tree.
251namespace tree
252{
253extern const char* version() noexcept;
254} // namespace tree
255template <>
256void setChoice<TreeInstance>(const std::string& choice);
257template <>
258void runCandidates<TreeInstance>(const std::vector<std::string>& candidates);
259} // namespace reg_ds
260} // namespace application
261
262//! @brief Reflect the data structure category name and alias name to the field in the mapping.
263#define REG_DS_REFLECT_FIRST_LEVEL_FIELD(category, alias) \
264 Field \
265 { \
266 REFLECTION_STR(MACRO_STRINGIFY(category)), &Type::MACRO_CONCAT(category, Opts), AttrList \
267 { \
268 Attr \
269 { \
270 REFLECTION_STR("alias"), MACRO_STRINGIFY(alias) \
271 } \
272 } \
273 }
274//! @brief Reflect the entry under the data structure category and choice name to the field in the mapping.
275#define REG_DS_REFLECT_SECOND_LEVEL_FIELD(entry, choice) \
276 Field \
277 { \
278 REFLECTION_STR(MACRO_STRINGIFY(entry)), Type::entry, AttrList \
279 { \
280 Attr \
281 { \
282 REFLECTION_STR("choice"), MACRO_STRINGIFY(choice) \
283 } \
284 } \
285 }
286//! @brief Static reflection for ApplyDataStructure. Used to map command line arguments.
287template <>
288struct utility::reflection::TypeInfo<application::reg_ds::ApplyDataStructure>
289 : public TypeInfoImpl<application::reg_ds::ApplyDataStructure>
290{
291 //! @brief Name.
292 static constexpr std::string_view name{"app-ds"};
293 // clang-format off
294 //! @brief Field list.
295 static constexpr FieldList fields
296 {
297 REG_DS_REFLECT_FIRST_LEVEL_FIELD(cache , c),
298 REG_DS_REFLECT_FIRST_LEVEL_FIELD(filter, f),
299 REG_DS_REFLECT_FIRST_LEVEL_FIELD(graph , g),
300 REG_DS_REFLECT_FIRST_LEVEL_FIELD(heap , H),
301 REG_DS_REFLECT_FIRST_LEVEL_FIELD(linear, l),
302 REG_DS_REFLECT_FIRST_LEVEL_FIELD(tree , t),
303 };
304 // clang-format on
305 //! @brief Attribute list.
306 static constexpr AttrList attrs{Attr{REFLECTION_STR("descr"), "apply data structure"}};
307};
308//! @brief Static reflection for CacheInstance. Used to map command line arguments.
309template <>
310struct utility::reflection::TypeInfo<application::reg_ds::CacheInstance>
311 : public TypeInfoImpl<application::reg_ds::CacheInstance>
312{
313 //! @brief Name.
314 static constexpr std::string_view name{"cache"};
315 // clang-format off
316 //! @brief Field list.
317 static constexpr FieldList fields
318 {
319 REG_DS_REFLECT_SECOND_LEVEL_FIELD(firstInFirstOut , fir),
320 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leastFrequentlyUsed, fre),
321 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leastRecentlyUsed , rec),
322 };
323 // clang-format on
324 //! @brief Attribute list.
325 static constexpr AttrList attrs{Attr{
326 REFLECTION_STR("descr"),
327 "cache-related choices\n"
328 "- fir First In First Out\n"
329 "- fre Least Frequently Used\n"
330 "- rec Least Recently Used\n"
331 "add the choices listed above"}};
332};
333//! @brief Static reflection for FilterInstance. Used to map command line arguments.
334template <>
335struct utility::reflection::TypeInfo<application::reg_ds::FilterInstance>
336 : public TypeInfoImpl<application::reg_ds::FilterInstance>
337{
338 //! @brief Name.
339 static constexpr std::string_view name{"filter"};
340 // clang-format off
341 //! @brief Field list.
342 static constexpr FieldList fields
343 {
344 REG_DS_REFLECT_SECOND_LEVEL_FIELD(bloom , blo),
345 REG_DS_REFLECT_SECOND_LEVEL_FIELD(quotient, quo),
346 };
347 // clang-format on
348 //! @brief Attribute list.
349 static constexpr AttrList attrs{Attr{
350 REFLECTION_STR("descr"),
351 "filter-related choices\n"
352 "- blo Bloom\n"
353 "- quo Quotient\n"
354 "add the choices listed above"}};
355};
356//! @brief Static reflection for GraphInstance. Used to map command line arguments.
357template <>
358struct utility::reflection::TypeInfo<application::reg_ds::GraphInstance>
359 : public TypeInfoImpl<application::reg_ds::GraphInstance>
360{
361 //! @brief Name.
362 static constexpr std::string_view name{"graph"};
363 // clang-format off
364 //! @brief Field list.
365 static constexpr FieldList fields
366 {
367 REG_DS_REFLECT_SECOND_LEVEL_FIELD(undirected, und),
368 REG_DS_REFLECT_SECOND_LEVEL_FIELD(directed , dir),
369 };
370 // clang-format on
371 //! @brief Attribute list.
372 static constexpr AttrList attrs{Attr{
373 REFLECTION_STR("descr"),
374 "graph-related choices\n"
375 "- und Undirected\n"
376 "- dir Directed\n"
377 "add the choices listed above"}};
378};
379//! @brief Static reflection for HeapInstance. Used to map command line arguments.
380template <>
381struct utility::reflection::TypeInfo<application::reg_ds::HeapInstance>
382 : public TypeInfoImpl<application::reg_ds::HeapInstance>
383{
384 //! @brief Name.
385 static constexpr std::string_view name{"heap"};
386 // clang-format off
387 //! @brief Field list.
388 static constexpr FieldList fields
389 {
390 REG_DS_REFLECT_SECOND_LEVEL_FIELD(binary , bin),
391 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leftist, lef),
392 REG_DS_REFLECT_SECOND_LEVEL_FIELD(skew , ske),
393 };
394 // clang-format on
395 //! @brief Attribute list.
396 static constexpr AttrList attrs{Attr{
397 REFLECTION_STR("descr"),
398 "heap-related choices\n"
399 "- bin Binary\n"
400 "- lef Leftist\n"
401 "- ske Skew\n"
402 "add the choices listed above"}};
403};
404//! @brief Static reflection for LinearInstance. Used to map command line arguments.
405template <>
406struct utility::reflection::TypeInfo<application::reg_ds::LinearInstance>
407 : public TypeInfoImpl<application::reg_ds::LinearInstance>
408{
409 //! @brief Name.
410 static constexpr std::string_view name{"linear"};
411 // clang-format off
412 //! @brief Field list.
413 static constexpr FieldList fields
414 {
415 REG_DS_REFLECT_SECOND_LEVEL_FIELD(doublyLinkedList, lin),
416 REG_DS_REFLECT_SECOND_LEVEL_FIELD(stack , sta),
417 REG_DS_REFLECT_SECOND_LEVEL_FIELD(queue , que),
418 };
419 // clang-format on
420 //! @brief Attribute list.
421 static constexpr AttrList attrs{Attr{
422 REFLECTION_STR("descr"),
423 "linear-related choices\n"
424 "- lin Doubly Linked List\n"
425 "- sta Stack\n"
426 "- que Queue\n"
427 "add the choices listed above"}};
428};
429//! @brief Static reflection for TreeInstance. Used to map command line arguments.
430template <>
431struct utility::reflection::TypeInfo<application::reg_ds::TreeInstance>
432 : public TypeInfoImpl<application::reg_ds::TreeInstance>
433{
434 //! @brief Name.
435 static constexpr std::string_view name{"tree"};
436 // clang-format off
437 //! @brief Field list.
438 static constexpr FieldList fields
439 {
440 REG_DS_REFLECT_SECOND_LEVEL_FIELD(binarySearch , bin),
441 REG_DS_REFLECT_SECOND_LEVEL_FIELD(adelsonVelskyLandis, ade),
442 REG_DS_REFLECT_SECOND_LEVEL_FIELD(splay , spl),
443 };
444 // clang-format on
445 //! @brief Attribute list.
446 static constexpr AttrList attrs{Attr{
447 REFLECTION_STR("descr"),
448 "tree-related choices\n"
449 "- bin Binary Search\n"
450 "- ade Adelson-Velsky-Landis\n"
451 "- spl Splay\n"
452 "add the choices listed above"}};
453};
454#undef REG_DS_REFLECT_FIRST_LEVEL_FIELD
455#undef REG_DS_REFLECT_SECOND_LEVEL_FIELD
456
457namespace application::reg_ds
458{
459//! @brief Alias for the type information.
460//! @tparam UDT - type of user defined data
461template <typename UDT>
462using TypeInfo = utility::reflection::TypeInfo<UDT>;
463//! @brief Alias for the category.
464using Category = ApplyDataStructure::Category;
465//! @brief Convert category enumeration to string.
466//! @param cat - target category
467//! @return category name
468consteval std::string_view toString(const Category cat)
469{
470 switch (cat)
471 {
472 case Category::cache:
473 return TypeInfo<CacheInstance>::name;
474 case Category::filter:
475 return TypeInfo<FilterInstance>::name;
476 case Category::graph:
477 return TypeInfo<GraphInstance>::name;
478 case Category::heap:
479 return TypeInfo<HeapInstance>::name;
480 case Category::linear:
481 return TypeInfo<LinearInstance>::name;
482 case Category::tree:
483 return TypeInfo<TreeInstance>::name;
484 default:
485 break;
486 }
487 return {};
488}
489//! @brief Get the bit flags of the category in data structure choices.
490//! @tparam Cat - target category
491//! @return reference of the category bit flags
492template <Category Cat>
493constexpr auto& categoryOpts()
494{
495 return std::invoke(
496 TypeInfo<ApplyDataStructure>::fields.find(REFLECTION_STR(toString(Cat))).value, manage::choiceApplier());
497}
498//! @brief The literal hash value of the abbreviation for the candidate instance.
499//! @tparam Inst - type of candidate instance
500//! @param instance - candidate instance
501//! @return literal hash value
502template <typename Inst>
503consteval std::size_t abbrLitHash(const Inst instance)
504{
505 static_assert(Bottom<Inst>::value == TypeInfo<Inst>::fields.size);
506 constexpr auto refl = REFLECTION_STR("choice");
507 std::size_t value = 0;
508 TypeInfo<Inst>::fields.findIf(
509 [refl, instance, &value](const auto field)
510 {
511 if (field.name == TypeInfo<Inst>::fields.nameOfValue(instance))
512 {
513 static_assert(field.attrs.contains(refl) && (field.attrs.size == 1));
514 const auto attr = field.attrs.find(refl);
515 static_assert(attr.hasValue);
516 value = utility::common::operator""_bkdrHash(attr.value);
517 return true;
518 }
519 return false;
520 });
521 return value;
522}
523} // namespace application::reg_ds
524