-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRouter.hpp
More file actions
103 lines (91 loc) · 4.58 KB
/
Router.hpp
File metadata and controls
103 lines (91 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#pragma once
#include "BooleanParser.hpp"
#include "StringParser.hpp"
#include "ArrayParser.hpp"
#include "CLIParser.hpp"
template<typename T>
static void pushCallback(const size_t insertionIndex, T& command, const int64_t commandDepth, std::deque<UCLI::Parser::CallbackObject>& callbacks) noexcept
{
// When inserting flags we need to sort them in a specific manner
if constexpr (std::is_same_v<T, UCLI::Flag>)
{
// If the flag is with a priority higher than SIZE_MAX / 2, then insert at the front of the queue.
// These are sorted after the fact
if (command.priority > (SIZE_MAX / 2))
callbacks.emplace_front(&command, false);
else
{
bool bPushed = false;
// Iterate call callbacks and count up until we hit commandDepth.
for (size_t a = 0, b = 0; a < callbacks.size(); a++)
{
// Skip other flags
if (!callbacks[a].bCommand)
continue;
// We're in a command, and we found the command at our required depth
if (b == commandDepth)
{
bPushed = true;
// Insert just after the current command
callbacks.insert(
callbacks.begin() + static_cast<std::remove_cvref_t<decltype(callbacks)>::difference_type>(a + 1),
{
.ptr = &command,
.bCommand = false
}
);
// Find the length of the flag sequence until the next command
size_t f = a + 1;
for (; f < callbacks.size() && !callbacks[f].bCommand; f++)
;
// Sort flags in descending order based on their priority
std::ranges::stable_sort(
callbacks.begin() + static_cast<std::remove_cvref_t<decltype(callbacks)>::difference_type>(a + 1),
callbacks.begin() + static_cast<std::remove_cvref_t<decltype(callbacks)>::difference_type>(f),
[](const UCLI::Parser::CallbackObject& x, const UCLI::Parser::CallbackObject& y) -> bool
{
return static_cast<UCLI::Flag*>(x.ptr)->priority > static_cast<UCLI::Flag*>(y.ptr)->priority;
}
);
break;
}
b++;
}
// If we never found and associated command for a flag this likely means that we don't have a current
// command to begin with so just push
if (!bPushed)
callbacks.emplace_back(&command, false);
}
}
else
{
// If the insertion index is equal to the size of the callbacks queue this means that the command order is correct:
// command -> flags. If it isn't it's because we've pushed flags before the current command. This happens when
// using flag probing where the command looks like: git clone --recursive https://...
if (insertionIndex == callbacks.size())
callbacks.emplace_back(&command, true);
else
callbacks.insert(callbacks.begin() + static_cast<std::remove_cvref_t<decltype(callbacks)>::difference_type>(insertionIndex), { .ptr = &command, .bCommand = true });
}
}
// This function routes the actual parsing of arguments and handling of syntax features to the command's corresponding
// parser
template<typename T>
static void executeCommand(int& i, const int argc, char** argv, T& command, const int64_t assignmentIndex, const char arrayDelimiter, const bool bToggle, const char flagPrefix, const bool bForcedDefault, const bool bProbingFlags, const int64_t commandDepth, std::deque<UCLI::Parser::CallbackObject>& callbacks, UCLI::Parser& p) noexcept
{
// Always insert commands at this index
size_t insertionIndex = callbacks.size();
if (command.type == UCLI_COMMAND_TYPE_BOOL)
loadBooleanCommand(i, argc, argv, command, assignmentIndex, bToggle, flagPrefix, bForcedDefault);
else if (command.type == UCLI_COMMAND_TYPE_STRING)
{
if (!loadStringCommand(i, argc, argv, command, assignmentIndex, bForcedDefault, flagPrefix, p))
return;
}
else if (command.type == UCLI_COMMAND_TYPE_ARRAY)
{
if (!loadArrayCommand(i, argc, argv, command, assignmentIndex, arrayDelimiter, flagPrefix, bForcedDefault, bProbingFlags, p))
return;
}
pushCallback(insertionIndex, command, commandDepth, callbacks);
}