47 inline std::istream&
getline (std::istream& stream, std::string&
string)
50 if (
string.size() > 0)
51 if (
string[
string.size()-1] == 015)
52 string.resize (
string.size()-1);
58 template <
typename X,
typename ReturnType =
int>
60 static constexpr int value () {
return 0; }
65 static constexpr int value () {
return std::numeric_limits<X>::max_digits10; }
70 static constexpr int value () {
return std::numeric_limits<typename X::Scalar>::max_digits10; }
74 struct max_digits<X, typename
std::enable_if<std::is_fundamental<typename X::value_type>::value && !std::is_fundamental<typename X::Scalar>::value, int>::type> {
NOMEMALIGN
75 static constexpr int value () {
return std::numeric_limits<typename X::value_type>::max_digits10; }
81 inline std::string&
add_line (std::string& original,
const std::string& new_line)
83 return original.size() ? (original +=
"\n" + new_line) : ( original = new_line );
88 inline std::string
shorten (
const std::string& text,
size_t longest = 40,
size_t prefix = 10)
90 if (text.size() > longest)
91 return (text.substr (0,prefix) +
"..." + text.substr (text.size()-longest+prefix+3));
98 inline std::string
lowercase (
const std::string&
string)
101 ret.resize (
string.size());
102 transform (
string.begin(),
string.end(), ret.begin(), tolower);
107 inline std::string
uppercase (
const std::string&
string)
110 ret.resize (
string.size());
111 transform (
string.begin(),
string.end(), ret.begin(), toupper);
116 inline std::string
printf (
const char* format, ...)
119 va_list list1, list2;
120 va_start (list1, format);
121 va_copy (list2, list1);
122 len = vsnprintf (
nullptr, 0, format, list1) + 1;
125 vsnprintf (buf, len, format, list2);
131 inline std::string
strip (
const std::string&
string,
const std::string& ws = {
" \0\t\r\n", 5},
bool left =
true,
bool right =
true)
133 std::string::size_type start = (left ?
string.find_first_not_of (ws) : 0);
134 if (start == std::string::npos)
136 std::string::size_type end = (right ?
string.find_last_not_of (ws) + 1 : std::string::npos);
137 return string.substr (start, end - start);
142 inline std::string
unquote (
const std::string&
string)
144 if (
string.size() <= 2)
146 if (!(
string.front() ==
'\"' &&
string.back() ==
'\"'))
148 const std::string substring =
string.substr(1,
string.size()-2);
149 if (std::none_of (substring.begin(), substring.end(), [] (
const char& c) { return c ==
'\"'; }))
156 inline void replace (std::string&
string,
char orig,
char final)
158 for (
auto& c:
string)
159 if (c == orig) c =
final;
162 inline void replace (std::string&
str,
const std::string& from,
const std::string&
to)
164 if (from.empty())
return;
165 size_t start_pos = 0;
166 while ((start_pos =
str.find (from, start_pos)) != std::string::npos) {
167 str.replace (start_pos, from.length(),
to);
168 start_pos +=
to.length();
174 const std::string&
string,
175 const char* delimiters =
" \t\n",
176 bool ignore_empty_fields =
false,
177 size_t num = std::numeric_limits<size_t>::max());
180 const std::string&
string,
181 bool ignore_empty_fields =
true,
182 size_t num = std::numeric_limits<size_t>::max())
184 return split (
string,
"\n", ignore_empty_fields,
num);
198 bool match (
const std::string& pattern,
const std::string& text,
bool ignore_case =
false);
207 assert (arg !=
nullptr);
210 if (arg[0] ==
'\0' || arg[1] ==
'\0' || arg[2] ==
'\0')
212 const unsigned char* uarg =
reinterpret_cast<const unsigned char*
> (arg);
213 if (uarg[0] == 0xE2 && uarg[1] == 0x80 && ( uarg[2] >= 0x90 && uarg[2] <= 0x95 ))
215 if (uarg[0] == 0xEF) {
216 if (uarg[1] == 0xB9 && ( uarg[2] == 0x98 || uarg[2] == 0xA3))
218 if (uarg[1] == 0xBC && uarg[2] == 0x8D)
225 inline size_t is_dash (
const std::string& arg)
228 return nbytes != 0 && nbytes == arg.size();
247 template <
class T>
inline std::string
str (
const T&
value,
int precision = 0)
249 std::ostringstream stream;
251 stream.precision (precision);
256 throw Exception (std::string(
"error converting type \"") +
typeid(T).
name() +
"\" value to string");
260 template <
class T>
inline T
to (
const std::string&
string)
262 const std::string stripped (
strip (
string));
263 std::istringstream stream (stripped);
268 const std::string lstring =
lowercase (stripped);
269 if (lstring ==
"nan")
270 return std::numeric_limits<T>::quiet_NaN();
271 else if (lstring ==
"-nan")
272 return -std::numeric_limits<T>::quiet_NaN();
273 else if (lstring ==
"inf")
274 return std::numeric_limits<T>::infinity();
275 else if (lstring ==
"-inf")
276 return -std::numeric_limits<T>::infinity();
278 throw Exception (
"error converting string \"" +
string +
"\" to type \"" +
typeid(T).
name() +
"\"");
279 }
else if (!stream.eof()) {
280 throw Exception (
"incomplete use of string \"" +
string +
"\" in conversion to type \"" +
typeid(T).
name() +
"\"");
285 template <>
inline bool to<bool> (
const std::string&
string)
292 return to<int> (
string);
297 std::ostringstream stream;
299 stream.precision (precision);
300 stream <<
value.real();
302 stream << std::showpos <<
value.imag() <<
"i";
304 throw Exception (
"error converting complex float value to string");
311 throw Exception (
"cannot convert empty string to complex float");
313 const std::string stripped =
strip (
string);
315 for (ssize_t i = -1; i <= ssize_t(stripped.size()); ++i) {
316 std::string first, second;
320 }
else if (i == ssize_t(stripped.size())) {
324 if (!(stripped[i] ==
'+' || stripped[i] ==
'-'))
326 first = stripped.substr(0, i);
327 second = stripped.substr(stripped[i] ==
'-' ? i : i+1);
329 if (!(second.back() ==
'i' || second.back() ==
'j'))
332 if (second.empty() || second ==
"-" || second ==
"+")
333 second.push_back (
'1');
335 candidates.push_back (
cfloat (to<float> (first), to<float> (second)));
339 if (candidates.empty())
340 throw Exception (
"error converting string \"" +
string +
"\" to complex float (no valid conversion)");
342 for (
size_t i = 1; i != candidates.size(); ++i) {
343 if (!(candidates[i].real() == candidates[0].real() ||
344 (std::isnan (candidates[i].real()) && std::isnan (candidates[0].real()))))
345 throw Exception (
"error converting string \"" +
string +
"\" to complex float (ambiguity in real component)");
346 if (!(candidates[i].imag() == candidates[0].imag() ||
347 (std::isnan (candidates[i].imag()) && std::isnan (candidates[0].imag()))))
348 throw Exception (
"error converting string \"" +
string +
"\" to complex float (ambiguity in imaginary component)");
350 return candidates[0];
355 std::ostringstream stream;
357 stream.precision (precision);
358 stream <<
value.real();
360 stream << std::showpos <<
value.imag() <<
"i";
362 throw Exception (
"error converting complex double value to string");
369 throw Exception (
"cannot convert empty string to complex double");
371 const std::string stripped =
strip (
string);
373 for (ssize_t i = -1; i <= ssize_t(stripped.size()); ++i) {
374 std::string first, second;
378 }
else if (i == ssize_t(stripped.size())) {
382 if (!(stripped[i] ==
'+' || stripped[i] ==
'-'))
384 first = stripped.substr(0, i);
385 second = stripped.substr(stripped[i] ==
'-' ? i : i+1);
387 if (!(second.back() ==
'i' || second.back() ==
'j'))
390 if (second.empty() || second ==
"-" || second ==
"+")
391 second.push_back (
'1');
393 candidates.push_back (
cdouble (to<double> (first), to<double> (second)));
397 if (candidates.empty())
398 throw Exception (
"error converting string \"" +
string +
"\" to complex double (no valid conversion)");
400 for (
size_t i = 1; i != candidates.size(); ++i) {
401 if (!(candidates[i].real() == candidates[0].real() ||
402 (std::isnan (candidates[i].real()) && std::isnan (candidates[0].real()))))
403 throw Exception (
"error converting string \"" +
string +
"\" to complex double (ambiguity in real component)");
404 if (!(candidates[i].imag() == candidates[0].imag() ||
405 (std::isnan (candidates[i].imag()) && std::isnan (candidates[0].imag()))))
406 throw Exception (
"error converting string \"" +
string +
"\" to complex double (ambiguity in imaginary component)");
408 return candidates[0];
421 template <
typename IntType>
424 typedef typename std::make_signed<IntType>::type SignedIntType;
425 if (!spec.size())
throw Exception (
"integer sequence specifier is empty");
427 auto to_unsigned = [&] (
const SignedIntType
value)
430 throw Exception (
"Impermissible negative value present in sequence \"" + spec +
"\"");
431 return IntType(
value);
435 std::string::size_type start = 0, end;
436 std::array<SignedIntType, 3>
num;
440 start = spec.find_first_not_of (
" \t", start);
441 if (start == std::string::npos)
443 end = spec.find_first_of (
" \t,:", start);
444 std::string token (
strip (spec.substr (start, end-start)));
446 if (last == std::numeric_limits<IntType>::max())
447 throw Exception (
"value of \"end\" is not known in number sequence \"" + spec +
"\"");
448 num[i] = SignedIntType(last);
450 else num[i] = to<SignedIntType> (spec.substr (start, end-start));
452 end = spec.find_first_not_of (
" \t", end);
453 char last_char = end < spec.size() ? spec[end] :
'\0';
454 if (last_char ==
':') {
457 if (i > 2)
throw Exception (
"invalid number range in number sequence \"" + spec +
"\"");
460 SignedIntType inc, last;
469 if (inc * (last -
num[0]) < 0)
471 for (; (inc > 0 ?
num[0] <= last :
num[0] >= last) ;
num[0] += inc)
472 V.push_back (to_unsigned(
num[0]));
474 else V.push_back (to_unsigned(
num[0]));
479 if (last_char ==
',')
482 while (end < spec.size());
485 throw Exception (E,
"can't parse integer sequence specifier \"" + spec +
"\"");
509 template <
typename T>
521 inline std::string
join (
const char*
const* null_terminated_array,
const std::string&
delimiter)
524 if (!null_terminated_array)
526 ret = null_terminated_array[0];
527 for (
const char*
const* p = null_terminated_array+1; *p; ++p)
#define VLA(name, type, num)
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
char delimiter(const std::string &filename)
std::complex< float > cfloat
void replace(std::string &string, char orig, char final)
std::complex< double > cdouble
cdouble to< cdouble >(const std::string &string)
bool consume_dash(const char *&arg)
match current character to a dash or any Unicode character that looks like one
vector< default_type > parse_floats(const std::string &spec)
std::string join(const vector< std::string > &V, const std::string &delimiter)
std::istream & getline(std::istream &stream, std::string &string)
read a line from the stream
std::string unquote(const std::string &string)
Remove quotation marks only if surrounding entire string.
std::string uppercase(const std::string &string)
return uppercase version of string
bool match(const std::string &pattern, const std::string &text, bool ignore_case=false)
std::string strip(const std::string &string, const std::string &ws={" \0\t\r\n", 5}, bool left=true, bool right=true)
cfloat to< cfloat >(const std::string &string)
bool to< bool >(const std::string &string)
std::string str< cdouble >(const cdouble &value, int precision)
std::string str(const T &value, int precision=0)
size_t char_is_dash(const char *arg)
match a dash or any Unicode character that looks like one
std::string lowercase(const std::string &string)
return lowercase version of string
vector< IntType > parse_ints(const std::string &spec, const IntType last=std::numeric_limits< IntType >::max())
vector< std::string > split_lines(const std::string &string, bool ignore_empty_fields=true, size_t num=std::numeric_limits< size_t >::max())
std::string shorten(const std::string &text, size_t longest=40, size_t prefix=10)
convert a long string to 'beginningofstring...endofstring' for display
std::string printf(const char *format,...)
std::string str< cfloat >(const cfloat &value, int precision)
vector< std::string > split(const std::string &string, const char *delimiters=" \t\n", bool ignore_empty_fields=false, size_t num=std::numeric_limits< size_t >::max())
T to(const std::string &string)
size_t is_dash(const std::string &arg)
match whole string to a dash or any Unicode character that looks like one
std::string & add_line(std::string &original, const std::string &new_line)
add a line to a string, taking care of inserting a newline if needed
static constexpr int value()
static constexpr int value()
static constexpr int value()
static constexpr int value()