LogIt++
Loading...
Searching...
No Matches
argument_utils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _LOGIT_ARGUMENT_UTILS_HPP_INCLUDED
3#define _LOGIT_ARGUMENT_UTILS_HPP_INCLUDED
6
7#include <tuple>
8#include <vector>
9
10namespace logit {
11
15 inline std::vector<VariableValue> args_to_array(std::vector<std::string>::const_iterator name_iter) {
16 return {};
17 }
18
26 template <typename T, typename... Ts>
27 std::vector<VariableValue> args_to_array(std::vector<std::string>::const_iterator name_iter, const T& first_arg, const Ts&... args) {
28 // Создаем вектор и добавляем первый элемент (имя, значение)
29 std::vector<VariableValue> result;
30 result.push_back(VariableValue(*name_iter, first_arg));
31 name_iter++;
32 // Рекурсивно добавляем оставшиеся элементы
33 auto tail_result = args_to_array(name_iter, args...);
34 result.insert(result.end(), tail_result.begin(), tail_result.end());
35 return result;
36 }
37
38 using crev_it_t = std::string::const_reverse_iterator;
39
44 bool is_closing_template(crev_it_t left_it, crev_it_t right_it) {
45 if (*left_it != '>' || left_it == right_it) return false;
46 --left_it; // move to right
47 while (left_it != right_it && (
48 *left_it == ' '
49 || *left_it == '\t'
50 || *left_it == '\n'
51 || *left_it == '\r'
52 || *left_it == '\f'
53 || *left_it == '\v')) {
54 --left_it;
55 }
56 return *left_it == ':' && (left_it != right_it) && *(left_it-1) == ':';
57 }
58
62 inline std::vector<std::string> split_arguments(const std::string& all_names) {
63 auto result = std::vector<std::string>{};
64 if (all_names.empty()) return result;
65
66 auto right_cut = all_names.crbegin();
67 auto left_cut = all_names.crbegin();
68 auto const left_end = all_names.crend();
69 auto parenthesis_count = int{0};
70 auto angle_bracket_count = int{0};
71
72 // Parse the arguments string backward. It is easier this way to check if a '<' or
73 // '>' character is either a comparison operator, or a opening and closing of
74 // templates arguments.
75 for (;;) {
76 if (left_cut != left_end && (left_cut+1) != left_end) {
77 // Ignore commas inside quotations (single and double)
78 if (*left_cut == '"' && *(left_cut+1) != '\\') {
79 // Don't split anything inside a string
80 ++left_cut;
81 while (!( // Will iterate with left_cut until the stop condition:
82 (left_cut+1) == left_end // The next position is the end iterator
83 || (*left_cut == '"' && *(left_cut+1) != '\\') // The current char the closing quotation
84 )) {
85 ++left_cut;
86 }
87 ++left_cut;
88 } else
89 if (*left_cut == '\'' && *(left_cut+1) != '\\') {
90 // Don't split a ',' (a comma between single quotation marks)
91 ++left_cut;
92 while (!( // Will iterate with left_cut until the stop condition:
93 (left_cut+1) == left_end // The next position is the end iterator
94 || (*left_cut == '\'' && *(left_cut+1) != '\\') // The current char is the closing quotation
95 )) {
96 ++left_cut;
97 }
98 ++left_cut;
99 }
100 }
101
102 if (left_cut == left_end ||
103 (*left_cut == ',' && parenthesis_count == 0 && angle_bracket_count == 0)){
104 // If it have found the comma separating two arguments, or the left ending
105 // of the leftmost argument.
106
107 // Remove the leading spaces
108 auto e_it = left_cut - 1;
109 while (*e_it == ' ') --e_it;
110 ++e_it;
111
112 // Remove the trailing spaces
113 while (*right_cut == ' ') ++right_cut;
114
115 result.emplace(result.begin(), e_it.base(), right_cut.base());
116 if (left_cut != left_end) {
117 right_cut = left_cut + 1;
118 }
119 } else
120 // It won't cut on a comma within parentheses, such as when the argument is a
121 // function call, as in IC(foo(1, 2))
122 if (*left_cut == ')') {
123 ++parenthesis_count;
124 } else
125 if (*left_cut == '(') {
126 --parenthesis_count;
127 } else
128 // It won't cut on a comma within a template argument list, such as in
129 // IC(std::is_same<int, int>::value)
130 if (is_closing_template(left_cut, right_cut)) {
131 ++angle_bracket_count;
132 } else if (*left_cut == '<' && angle_bracket_count > 0) {
133 --angle_bracket_count;
134 }
135
136 if (left_cut == left_end) {
137 break;
138 } else {
139 ++left_cut;
140 }
141 }
142 return result;
143 }
144
145}; // namespace logit
146
147#endif // _LOGIT_ARGUMENT_UTILS_HPP_INCLUDED
The primary namespace for the LogIt++ library.
std::vector< std::string > split_arguments(const std::string &all_names)
Splits a string of argument names into individual names, ignoring nested templates,...
bool is_closing_template(crev_it_t left_it, crev_it_t right_it)
Checks if the '>' character is the closing of a template argument list.
std::string::const_reverse_iterator crev_it_t
std::vector< VariableValue > args_to_array(std::vector< std::string >::const_iterator name_iter)
Base case of recursion for argument conversion — when there are no more arguments.
Structure for storing values of various types, including enumerations.