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-2025 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 // _PRECOMPILED_HEADER
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 Set choice.
182//! @tparam Inst - type of target instance
183//! @param choice - target choice
184template <typename Inst>
185void setChoice(const std::string& choice);
186//! @brief Run candidates.
187//! @tparam Inst - type of target instance
188//! @param candidates - container for the candidate target choices
189template <typename Inst>
190void runCandidates(const std::vector<std::string>& candidates);
191
192//! @brief Register cache.
193namespace cache
194{
195extern const char* version() noexcept;
196} // namespace cache
197template <>
198void setChoice<CacheInstance>(const std::string& choice);
199template <>
200void runCandidates<CacheInstance>(const std::vector<std::string>& candidates);
201
202//! @brief Register filter.
203namespace filter
204{
205extern const char* version() noexcept;
206} // namespace filter
207template <>
208void setChoice<FilterInstance>(const std::string& choice);
209template <>
210void runCandidates<FilterInstance>(const std::vector<std::string>& candidates);
211
212//! @brief Register graph.
213namespace graph
214{
215extern const char* version() noexcept;
216} // namespace graph
217template <>
218void setChoice<GraphInstance>(const std::string& choice);
219template <>
220void runCandidates<GraphInstance>(const std::vector<std::string>& candidates);
221
222//! @brief Register heap.
223namespace heap
224{
225extern const char* version() noexcept;
226} // namespace heap
227template <>
228void setChoice<HeapInstance>(const std::string& choice);
229template <>
230void runCandidates<HeapInstance>(const std::vector<std::string>& candidates);
231
232//! @brief Register linear.
233namespace linear
234{
235extern const char* version() noexcept;
236} // namespace linear
237template <>
238void setChoice<LinearInstance>(const std::string& choice);
239template <>
240void runCandidates<LinearInstance>(const std::vector<std::string>& candidates);
241
242//! @brief Register tree.
243namespace tree
244{
245extern const char* version() noexcept;
246} // namespace tree
247template <>
248void setChoice<TreeInstance>(const std::string& choice);
249template <>
250void runCandidates<TreeInstance>(const std::vector<std::string>& candidates);
251} // namespace reg_ds
252} // namespace application
253
254//! @brief Reflect the data structure category name and alias name to the field in the mapping.
255#define REG_DS_REFLECT_FIRST_LEVEL_FIELD(category, alias) \
256 Field \
257 { \
258 REFLECTION_STR(MACRO_STRINGIFY(category)), &Type::MACRO_CONCAT(category, Opts), AttrList \
259 { \
260 Attr \
261 { \
262 REFLECTION_STR("alias"), MACRO_STRINGIFY(alias) \
263 } \
264 } \
265 }
266//! @brief Reflect the entry under the data structure category and choice name to the field in the mapping.
267#define REG_DS_REFLECT_SECOND_LEVEL_FIELD(entry, choice) \
268 Field \
269 { \
270 REFLECTION_STR(MACRO_STRINGIFY(entry)), Type::entry, AttrList \
271 { \
272 Attr \
273 { \
274 REFLECTION_STR("choice"), MACRO_STRINGIFY(choice) \
275 } \
276 } \
277 }
278//! @brief Static reflection for ApplyDataStructure. Used to map command line arguments.
279template <>
280struct utility::reflection::TypeInfo<application::reg_ds::ApplyDataStructure>
281 : public TypeInfoImpl<application::reg_ds::ApplyDataStructure>
282{
283 //! @brief Name.
284 static constexpr std::string_view name{"app-ds"};
285 // clang-format off
286 //! @brief Field list.
287 static constexpr FieldList fields
288 {
289 REG_DS_REFLECT_FIRST_LEVEL_FIELD(cache , c),
290 REG_DS_REFLECT_FIRST_LEVEL_FIELD(filter, f),
291 REG_DS_REFLECT_FIRST_LEVEL_FIELD(graph , g),
292 REG_DS_REFLECT_FIRST_LEVEL_FIELD(heap , H),
293 REG_DS_REFLECT_FIRST_LEVEL_FIELD(linear, l),
294 REG_DS_REFLECT_FIRST_LEVEL_FIELD(tree , t),
295 };
296 // clang-format on
297 //! @brief Attribute list.
298 static constexpr AttrList attrs{Attr{REFLECTION_STR("descr"), "apply data structure"}};
299};
300//! @brief Static reflection for CacheInstance. Used to map command line arguments.
301template <>
302struct utility::reflection::TypeInfo<application::reg_ds::CacheInstance>
303 : public TypeInfoImpl<application::reg_ds::CacheInstance>
304{
305 //! @brief Name.
306 static constexpr std::string_view name{"cache"};
307 // clang-format off
308 //! @brief Field list.
309 static constexpr FieldList fields
310 {
311 REG_DS_REFLECT_SECOND_LEVEL_FIELD(firstInFirstOut , fir),
312 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leastFrequentlyUsed, fre),
313 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leastRecentlyUsed , rec),
314 };
315 // clang-format on
316 //! @brief Attribute list.
317 static constexpr AttrList attrs{Attr{
318 REFLECTION_STR("descr"),
319 "cache-related choices\n"
320 "- fir First In First Out\n"
321 "- fre Least Frequently Used\n"
322 "- rec Least Recently Used\n"
323 "add the choices listed above"}};
324};
325//! @brief Static reflection for FilterInstance. Used to map command line arguments.
326template <>
327struct utility::reflection::TypeInfo<application::reg_ds::FilterInstance>
328 : public TypeInfoImpl<application::reg_ds::FilterInstance>
329{
330 //! @brief Name.
331 static constexpr std::string_view name{"filter"};
332 // clang-format off
333 //! @brief Field list.
334 static constexpr FieldList fields
335 {
336 REG_DS_REFLECT_SECOND_LEVEL_FIELD(bloom , blo),
337 REG_DS_REFLECT_SECOND_LEVEL_FIELD(quotient, quo),
338 };
339 // clang-format on
340 //! @brief Attribute list.
341 static constexpr AttrList attrs{Attr{
342 REFLECTION_STR("descr"),
343 "filter-related choices\n"
344 "- blo Bloom\n"
345 "- quo Quotient\n"
346 "add the choices listed above"}};
347};
348//! @brief Static reflection for GraphInstance. Used to map command line arguments.
349template <>
350struct utility::reflection::TypeInfo<application::reg_ds::GraphInstance>
351 : public TypeInfoImpl<application::reg_ds::GraphInstance>
352{
353 //! @brief Name.
354 static constexpr std::string_view name{"graph"};
355 // clang-format off
356 //! @brief Field list.
357 static constexpr FieldList fields
358 {
359 REG_DS_REFLECT_SECOND_LEVEL_FIELD(undirected, und),
360 REG_DS_REFLECT_SECOND_LEVEL_FIELD(directed , dir),
361 };
362 // clang-format on
363 //! @brief Attribute list.
364 static constexpr AttrList attrs{Attr{
365 REFLECTION_STR("descr"),
366 "graph-related choices\n"
367 "- und Undirected\n"
368 "- dir Directed\n"
369 "add the choices listed above"}};
370};
371//! @brief Static reflection for HeapInstance. Used to map command line arguments.
372template <>
373struct utility::reflection::TypeInfo<application::reg_ds::HeapInstance>
374 : public TypeInfoImpl<application::reg_ds::HeapInstance>
375{
376 //! @brief Name.
377 static constexpr std::string_view name{"heap"};
378 // clang-format off
379 //! @brief Field list.
380 static constexpr FieldList fields
381 {
382 REG_DS_REFLECT_SECOND_LEVEL_FIELD(binary , bin),
383 REG_DS_REFLECT_SECOND_LEVEL_FIELD(leftist, lef),
384 REG_DS_REFLECT_SECOND_LEVEL_FIELD(skew , ske),
385 };
386 // clang-format on
387 //! @brief Attribute list.
388 static constexpr AttrList attrs{Attr{
389 REFLECTION_STR("descr"),
390 "heap-related choices\n"
391 "- bin Binary\n"
392 "- lef Leftist\n"
393 "- ske Skew\n"
394 "add the choices listed above"}};
395};
396//! @brief Static reflection for LinearInstance. Used to map command line arguments.
397template <>
398struct utility::reflection::TypeInfo<application::reg_ds::LinearInstance>
399 : public TypeInfoImpl<application::reg_ds::LinearInstance>
400{
401 //! @brief Name.
402 static constexpr std::string_view name{"linear"};
403 // clang-format off
404 //! @brief Field list.
405 static constexpr FieldList fields
406 {
407 REG_DS_REFLECT_SECOND_LEVEL_FIELD(doublyLinkedList, lin),
408 REG_DS_REFLECT_SECOND_LEVEL_FIELD(stack , sta),
409 REG_DS_REFLECT_SECOND_LEVEL_FIELD(queue , que),
410 };
411 // clang-format on
412 //! @brief Attribute list.
413 static constexpr AttrList attrs{Attr{
414 REFLECTION_STR("descr"),
415 "linear-related choices\n"
416 "- lin Doubly Linked List\n"
417 "- sta Stack\n"
418 "- que Queue\n"
419 "add the choices listed above"}};
420};
421//! @brief Static reflection for TreeInstance. Used to map command line arguments.
422template <>
423struct utility::reflection::TypeInfo<application::reg_ds::TreeInstance>
424 : public TypeInfoImpl<application::reg_ds::TreeInstance>
425{
426 //! @brief Name.
427 static constexpr std::string_view name{"tree"};
428 // clang-format off
429 //! @brief Field list.
430 static constexpr FieldList fields
431 {
432 REG_DS_REFLECT_SECOND_LEVEL_FIELD(binarySearch , bin),
433 REG_DS_REFLECT_SECOND_LEVEL_FIELD(adelsonVelskyLandis, ade),
434 REG_DS_REFLECT_SECOND_LEVEL_FIELD(splay , spl),
435 };
436 // clang-format on
437 //! @brief Attribute list.
438 static constexpr AttrList attrs{Attr{
439 REFLECTION_STR("descr"),
440 "tree-related choices\n"
441 "- bin Binary Search\n"
442 "- ade Adelson-Velsky-Landis\n"
443 "- spl Splay\n"
444 "add the choices listed above"}};
445};
446#undef REG_DS_REFLECT_FIRST_LEVEL_FIELD
447#undef REG_DS_REFLECT_SECOND_LEVEL_FIELD
448
449namespace application::reg_ds
450{
451//! @brief Alias for the type information.
452//! @tparam UDT - type of user defined data
453template <typename UDT>
454using TypeInfo = utility::reflection::TypeInfo<UDT>;
455//! @brief Alias for the category.
456using Category = ApplyDataStructure::Category;
457//! @brief Convert category enumeration to string.
458//! @param cat - target category
459//! @return category name
460consteval std::string_view toString(const Category cat)
461{
462 switch (cat)
463 {
464 case Category::cache:
465 return TypeInfo<CacheInstance>::name;
466 case Category::filter:
467 return TypeInfo<FilterInstance>::name;
468 case Category::graph:
469 return TypeInfo<GraphInstance>::name;
470 case Category::heap:
471 return TypeInfo<HeapInstance>::name;
472 case Category::linear:
473 return TypeInfo<LinearInstance>::name;
474 case Category::tree:
475 return TypeInfo<TreeInstance>::name;
476 default:
477 break;
478 }
479 return {};
480}
481//! @brief Get the bit flags of the category in data structure choices.
482//! @tparam Cat - target category
483//! @return reference of the category bit flags
484template <Category Cat>
485constexpr auto& categoryOpts()
486{
487 return std::invoke(
488 TypeInfo<ApplyDataStructure>::fields.find(REFLECTION_STR(toString(Cat))).value, manage::choiceApplier());
489}
490//! @brief The literal hash value of the abbreviation for the candidate instance.
491//! @tparam Inst - type of candidate instance
492//! @param instance - candidate instance
493//! @return literal hash value
494template <typename Inst>
495consteval std::size_t abbrLitHash(const Inst instance)
496{
497 static_assert(Bottom<Inst>::value == TypeInfo<Inst>::fields.size);
498 constexpr auto refl = REFLECTION_STR("choice");
499 std::size_t value = 0;
500 TypeInfo<Inst>::fields.findIf(
501 [refl, instance, &value](const auto field)
502 {
503 if (field.name == TypeInfo<Inst>::fields.nameOfValue(instance))
504 {
505 static_assert(field.attrs.contains(refl) && (field.attrs.size == 1));
506 const auto attr = field.attrs.find(refl);
507 static_assert(attr.hasValue);
508 value = utility::common::operator""_bkdrHash(attr.value);
509 return true;
510 }
511 return false;
512 });
513 return value;
514}
515} // namespace application::reg_ds
516