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