41std::string format_string(
const char *_format, va_list _arguments)
43 if (!_format)
return {};
45 va_list arguments_copy;
46 va_copy(arguments_copy, _arguments);
47 const int required_size = std::vsnprintf(
nullptr, 0, _format, arguments_copy);
48 va_end(arguments_copy);
49 if (required_size < 0)
return {};
51 std::string result(
static_cast<std::size_t
>(required_size) + 1,
'\0');
52 std::vsnprintf(result.data(), result.size(), _format, _arguments);
53 result.resize(
static_cast<std::size_t
>(required_size));
57unsigned char unsigned_character(
char _character)
59 return static_cast<unsigned char>(_character);
65 normalized.reserve(_input.size());
66 for (
const char character : _input) {
67 if (character ==
' ')
continue;
68 normalized += (_replace_comma && character ==
',') ?
'.' : character;
75std::string
tkn::wrap_text(
const tkstring &_text,
size_t _first_content_col,
size_t _continuation_col,
size_t _max_line_width)
77 const size_t min_content_width = 20;
78 const size_t first_avail = _first_content_col < _max_line_width ? _max_line_width - _first_content_col : min_content_width;
79 const size_t continuation_avail = _continuation_col < _max_line_width ? _max_line_width - _continuation_col : min_content_width;
80 const std::string continuation_indent(_continuation_col,
' ');
82 auto wrap_paragraph = [&](
const std::string &_paragraph,
size_t _first_avail) {
85 bool first_chunk =
true;
86 while (pos < _paragraph.size()) {
87 if (!first_chunk) result +=
"\n" + continuation_indent;
88 const size_t content_avail = first_chunk ? _first_avail : continuation_avail;
89 if (_paragraph.size() - pos <= content_avail) {
90 result += _paragraph.substr(pos);
93 size_t wrap_at = _paragraph.rfind(
' ', pos + content_avail);
94 if (wrap_at == std::string::npos || wrap_at <= pos) {
95 result += _paragraph.substr(pos, content_avail);
98 result += _paragraph.substr(pos, wrap_at - pos);
100 while (pos < _paragraph.size() && _paragraph[pos] ==
' ') pos++;
109 bool first_para =
true;
110 for (
auto ¶ : paragraphs) {
111 if (!first_para) wrapped +=
"\n" + continuation_indent;
112 wrapped += wrap_paragraph(para, first_para ? first_avail : continuation_avail);
120 std::transform(begin(), end(), begin(),[](
unsigned char _c){
return std::tolower(_c); });
126 std::transform(begin(), end(), begin(),[](
unsigned char _c){
return std::toupper(_c); });
142 bool has_digit =
false;
143 if (empty())
return false;
144 for (
const char character : *
this) {
145 if (character ==
' ')
continue;
146 if (!std::isdigit(unsigned_character(character)))
return false;
169 const tkstring normalized = normalized_number(*
this,
true);
170 if (normalized.empty())
return false;
172 const double value = std::strtod(normalized.c_str(), &end);
173 return end != normalized.c_str() && *end ==
'\0' && std::isfinite(value);
212 if (find(
' ') == npos)
return std::atoi(data());
213 return std::atoi(normalized_number(*
this,
false).data());
218 if (find(
' ') == npos)
return std::atoll(data());
219 return std::atoll(normalized_number(*
this,
false).data());
228 if (find(
',') == npos && find(
' ') == npos)
return std::atof(data());
229 return std::atof(normalized_number(*
this,
true).data());
239 if (!_s || _pos > size())
return npos;
242 const std::string_view pattern(_s);
243 if (pattern.empty())
return _pos;
244 const auto match_position = std::search(
245 begin() +
static_cast<std::ptrdiff_t
>(_pos), end(),
246 pattern.begin(), pattern.end(),
247 [](
char left,
char right) {
248 return std::tolower(unsigned_character(left)) ==
249 std::tolower(unsigned_character(right));
251 return match_position == end() ? npos :
static_cast<size_t>(match_position - begin());
261 if (!_s)
return false;
262 if (_cmp ==
kExact)
return compare(_s) == 0;
263 const std::string_view other(_s);
264 return size() == other.size() && std::equal(
265 begin(), end(), other.begin(),
266 [](
char left,
char right) {
267 return std::tolower(unsigned_character(left)) ==
268 std::tolower(unsigned_character(right));
274 if (!_s)
return false;
276#if defined(__cpp_lib_starts_ends_with) && __cpp_lib_starts_ends_with >= 201711L
277 if (_cmp ==
kExact)
return std::string::ends_with(_s);
280 size_t l = strlen(_s);
281 if (l > length())
return false;
282 const auto offset = length() - l;
283 if (_cmp ==
kExact)
return compare(offset, l, _s) == 0;
285 begin() +
static_cast<std::ptrdiff_t
>(offset), end(), _s,
286 [](
char left,
char right) {
287 return std::tolower(unsigned_character(left)) ==
288 std::tolower(unsigned_character(right));
294 std::vector<tkstring> tokens;
295 if (empty())
return tokens;
296 if (_delim.empty()) {
297 tokens.push_back(*
this);
301 size_t start = find_first_not_of(_delim);
302 while (start != npos) {
303 const size_t stop = find_first_of(_delim, start);
304 tokens.emplace_back(std::string::substr(start, stop - start));
305 if (stop == npos)
break;
306 start = find_first_not_of(_delim, stop);
313 std::vector<tkstring> tokens;
314 if (empty())
return tokens;
315 if (_delim.empty()) {
316 tokens.push_back(*
this);
319 size_t start = 0, pos = 0;
322 while ((pos = find(_delim, start)) != npos) {
324 if (token.length()) {
325 tokens.push_back(token);
328 start = pos + _delim.length();
333 if (token.length()) {
334 tokens.push_back(token);
342 if (_s1 && _ls1 > 0) {
344 while ((pos = find(_s1,pos,_ls1)) != npos) {
345 replace(pos, _ls1, _s2, _ls2);
354 std::size_t found = find_last_of(_s1);
362 std::size_t found = find_last_of(_s1);
371 va_start(argptr, _format);
372 tkstring result(format_string(_format, argptr));
385 for(
size_t i=0 ; i<length() ; i++) {
386 if ((*
this)[i] >=
'a' && (*
this)[i] <=
'z') {
387 (*this)[i] -= (
'a' -
'A');
398 const char *cp = data();
399 size_t len = length();
401 for (
size_t i = 0; i < len; ++i)
402 if (std::isalpha(unsigned_character(cp[i])))
412 const char *cp = data();
413 size_t len = length();
415 for (
size_t i = 0; i < len; ++i)
416 if (!std::isalpha(unsigned_character(cp[i])))
429 const char *cp = data();
430 size_t len = length();
431 if (len == 0)
return false;
432 for (
size_t i = 0; i < len; ++i)
433 if (!std::isalpha(unsigned_character(cp[i])))
442 thread_local std::array<std::string, 8> buffers;
443 thread_local std::size_t next_buffer = 0;
444 std::string &result = buffers[next_buffer++ % buffers.size()];
447 va_start(argptr, _format);
448 result = format_string(_format, argptr);
450 return result.c_str();
461 tkstring sy_dec, sy_exp, sey_dec, sey_exp;
462 double y_dec, ey_dec;
466 std::vector<tkstring> loa_y = sy.
tokenize(
"e");
467 sy_dec = loa_y.front();
468 sy_exp = loa_y.back();
470 y_dec = sy_dec.
atof();
471 y_exp = sy_exp.
atoi();
474 std::vector<tkstring> loa_ey = sey.
tokenize(
"e");
476 sey_dec = loa_ey.front();
477 sey_exp = loa_ey.back();
479 ey_dec = sey_dec.
atof();
480 ey_exp = sey_exp.
atoi();
482 double err = ey_dec * pow(10., ey_exp - y_exp);
488 if (y_exp == ey_exp) s =
Form(
"%1.2g.0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
489 else s =
Form(
"%1.3g.0(%g.0).10$^{%d}$", y_dec, err, y_exp);
491 if (y_exp == ey_exp) s =
Form(
"%1.2g.0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
492 else s =
Form(
"%1.3g.0(%g0).10$^{%d}$", y_dec, err, y_exp);
494 if (y_exp == ey_exp) s =
Form(
"%1.2g.0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
495 else s =
Form(
"%1.3g.0(%g).10$^{%d}$", y_dec, err, y_exp);
497 }
else if (
Form(
"%1.3g", y_dec) ==
Form(
"%1.2g", y_dec) &&
Form(
"%1.2g", y_dec).
contains(
".") && err < 1) {
499 if (y_exp == ey_exp) s =
Form(
"%1.2g0(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
500 else s =
Form(
"%1.3g0(%g.0).10$^{%d}$", y_dec, err, y_exp);
502 if (y_exp == ey_exp) s =
Form(
"%1.2g0(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
503 else s =
Form(
"%1.3g0(%g0).10$^{%d}$", y_dec, err, y_exp);
505 if (y_exp == ey_exp) s =
Form(
"%1.2g0(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
506 else s =
Form(
"%1.3g0(%g).10$^{%d}$", y_dec, err, y_exp);
509 if (y_exp == ey_exp) s =
Form(
"%1.2g(%g.0).10$^{%d}$", y_dec, ey_dec, y_exp);
510 else s =
Form(
"%1.3g(%g.0).10$^{%d}$", y_dec, err, y_exp);
512 if (y_exp == ey_exp) s =
Form(
"%1.2g(%g0).10$^{%d}$", y_dec, ey_dec, y_exp);
513 else s =
Form(
"%1.3g(%g0).10$^{%d}$", y_dec, err, y_exp);
515 if (y_exp == ey_exp) s =
Form(
"%1.2g(%g).10$^{%d}$", y_dec, ey_dec, y_exp);
516 else s =
Form(
"%1.3g(%g).10$^{%d}$", y_dec, err, y_exp);;
538 if (_st.empty())
return 0;
542 while ((pos = find(_st,pos)) != npos) {
557 result.reserve(size());
558 bool pending_space =
false;
559 for (
const char character : *
this) {
560 const bool whitespace = character ==
' ' || character ==
'\n' || character ==
'\t';
562 pending_space = !result.empty();
565 if (pending_space) result +=
' ';
567 pending_space =
false;
587 if (pat ==
"*")
return true;
589 std::vector<tkstring> tok = pat.
tokenize(
"*");
590 int n_tok = tok.size();
600 int idx = 0, num = 0;
601 for (
int ii = 0; ii < n_tok; ii += 1) {
602 idx =
index(tok.at(ii), idx);
608 return (num == n_tok);
618 if(_skip_white) getline(_strm >> std::ws, *
this);
619 else getline(_strm, *
this);
626 if(
error.is_empty())
return -1.;
644 double precision = 1.0;
int expo;
size_t l1,l2;
649 if ( l1 == std::string::npos ) {
650 if ( l2 == std::string::npos )
655 precision = pow(10.,expo);
658 if ( l2 == std::string::npos ) {
659 expo = - (st.size() - l1 - 1);
660 precision = pow(10.0,expo);
665 expo = - (l2 - l1 - 1) + expo;
666 precision = pow(10.0,expo);
669 if ( precision < 0 ) precision = -1.0 * precision;
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
tkstring extract_alpha()
Returns a tkstring composed only of the alphabetic letters of the original tkstring.
tkstring strip_all_extra_white_space() const
tkstring copy() const
Returns a copy of this string.
tkstring & to_lower()
Change all letters to lower case.
static const char * form(const char *_format,...)
bool is_float() const
Checks if string contains a floating point or integer number.
tkstring get_last_occurence(const char *_s1)
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
static tkstring Form(const char *_format,...)
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
std::vector< tkstring > tokenize_from_string(const tkstring &_delim) const
Create a vector of string separated by a full string as delimiter.
bool match(const char *_pattern) const
bool is_alpha() const
Checks whether tkstring is only composed of alphabetic letters.
std::istream & read_line(std::istream &_strm, bool _skip_white=true)
tkstring::read_line
int atoi() const
Converts a string to integer value.
bool ends_with(const char *_s, ECaseCompare _cmp=kExact) const
static double get_absolute_error(tkstring val, tkstring error)
Get absolute uncertainty from value and error strings (1.27 4 -> 0.04), returns -1 in case of empty e...
bool equal_to(const char *_s, ECaseCompare _cmp=kExact) const
Returns true if the string and _s are identical.
size_t index(const char *_s, size_t _pos=0, ECaseCompare _cmp=kExact) const
Returns the index of the substring _s.
tkstring remove_alpha()
Returns a tkstring composed only of the non alphabetic letters of the original tkstring.
tkstring & remove_all_extra_white_space()
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
int count_string(const tkstring &_st) const
bool begins_with(const char *_s, ECaseCompare _cmp=kExact) const
tkstring & capitalize()
Change first letter of string from lower to upper case.
static double get_precision(tkstring _st)
Extract the precision for a given ENSDF data.
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
bool is_digit() const
Checks if all characters in string are digits (0-9) or whitespaces.
int64_t atoll() const
Converts a string to long integer value.
tkstring remove_last_occurence(const char *_s1)
double atof() const
Converts a string to double value.
tkstring & to_upper()
Change all letters to upper case.
std::string wrap_text(const tkstring &_text, size_t _first_content_col, size_t _continuation_col, size_t _max_line_width=80)
tklog & error(tklog &log)