-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvariadic_parser.hpp
More file actions
162 lines (138 loc) · 3.72 KB
/
variadic_parser.hpp
File metadata and controls
162 lines (138 loc) · 3.72 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <string>
#include <stdexcept>
#include <stdexcept>
#include <sstream>
// bool converter
void convert(std::string& str, bool& b) // can throw std::out_of_range, std::invalid_argument
{
transform(str.begin(), str.end(), str.begin(), ::tolower);
b = (str == "true" ? true : false);
};
// double converter
void convert(const std::string& str, double& d) // can throw std::out_of_range, std::invalid_argument
{
d = std::stod(str);
};
// int converter
void convert(const std::string& str, int& i) // can throw std::out_of_range, std::invalid_argument
{
i = std::stoi(str);
};
// float converter
void convert(const std::string& str, float& f) // can throw std::out_of_range, std::invalid_argument
{
f = std::stof(str);
};
// add your own converts here following as above.
// catch custom exceptions in from_string below and handle
//
//
/* "integral" concept: equal to true, if T is the type bool, char, char8_t (since C++20),
* char16_t, char32_t, wchar_t, short, int, long, long long, or any
* implementation-defined extended integer types, including any signed,
* unsigned, and cv-qualified variants. Otherwise, value is equal to false
*/
template<typename T>
concept arithmetic = std::integral<T> or std::floating_point<T>;
template <typename T>
requires arithmetic<T>
void from_string(const std::string& input, T& arg, size_t& pos, const char separator)
{
std::string to_convert;
try
{
size_t loc = input.find(separator, pos);
if (loc == std::string::npos)
{
loc = input.length();
}
to_convert = input.substr(pos, loc-pos);
convert(to_convert, arg);
pos = loc +1;
}
catch (const std::out_of_range& oor_ex)
{
std::ostringstream oss;
oss << "Exception: string conversion (range) at pos: " << pos;
throw std::out_of_range(oss.str());
}
catch (const std::invalid_argument& ia_ex)
{
std::ostringstream oss;
oss << "Exception: string conversion (invalid) at pos: " << pos;
throw std::invalid_argument(oss.str());
}
catch (const std::exception & ex)
{
std::ostringstream oss;
oss << "Exception: string conversion (general) at pos: " << pos << std::endl;
throw;
}
catch (...)
{
std::cerr << "Exception: string conversion (critical) impossible for arg: "
<< to_convert << ", pos: " << pos << ", to type " << std::endl;
}
}
void from_string(const std::string& input, std::string& arg, size_t& pos, const char separator)
{
try
{
size_t loc = input.find(separator,pos);
if (loc == std::string::npos)
{
loc = input.length();
}
arg = input.substr(pos, loc-pos);
arg.erase(std::remove_if(arg.begin(), arg.end(), ::isspace), arg.end());
pos = loc+1;
}
catch (...)
{
std::cerr << "ERROR cannot parse input: " << input << ", pos: " << pos << std::endl;
arg = "NULL";
}
};
void from_string(const std::string& input, char& arg, size_t& pos, const char separator)
{
try
{
// cater for input (',' is separator) "1,2, S , 12.2"
// where we are looking for the S char
while (pos < input.size())
{
if (std::isspace(input[pos]))
{
++pos;
}
else if (std::isalpha(input[pos]))
{
arg = input[pos];
++pos;
}
else if (input[pos] == separator)
{
pos+=1;
break;
}
}
}
catch (...)
{
std::cerr << "Rubbish input: " << input << ", " << separator << std::endl;
arg = 'X';
}
};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
void parse_line(size_t start_pos, std::string& input, const char separator)
{
};
#pragma GCC diagnostic pop
template <typename P1 , typename ...Param>
void parse_line(size_t start_pos, std::string& input, const char separator, P1& p1 , Param&... args)
{
from_string(input, p1, start_pos, separator);
parse_line(start_pos, input, separator, args...);
}