5#if __cplusplus >= 201703L
13 return c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r';
17 return c ==
'.' || c ==
',' || c ==
';' || c ==
':';
21 return c >=
'0' && c <=
'9';
27 return c >=
'a' && c <=
'z';
31const unsigned char AE =
static_cast<unsigned char>(142);
32const unsigned char ae =
static_cast<unsigned char>(132);
33const unsigned char OE =
static_cast<unsigned char>(153);
34const unsigned char oe =
static_cast<unsigned char>(148);
35const unsigned char UE =
static_cast<unsigned char>(154);
36const unsigned char ue =
static_cast<unsigned char>(129);
37const unsigned char ss =
static_cast<unsigned char>(225);
41 if (c >=
'A' && c <=
'Z')
42 return (c -
'A') +
'a';
45 case OE:
return (
char)oe;
46 case UE:
return (
char)ue;
47 case AE:
return (
char)ae;
52std::string
to_hex(uint8_t v,
bool use_upper_case)
54 static const char lc_hex_digits[] =
"0123456789abcdef";
55 static const char uc_hex_digits[] =
"0123456789ABCDEF";
56 const char* hex_digits = use_upper_case ? uc_hex_digits : lc_hex_digits;
57 char res[2] = { hex_digits[v / 16], hex_digits[v & 15] };
58 return std::string(res, 2);
80 return 10 + (c -
'A');
87 return 10 + (c -
'a');
93 std::vector<uint8_t> bytes;
94 for (
size_t i = 0; i < byte_str.size(); i += 2)
101 for (
unsigned int i = 0; i < s.size(); ++i)
108 if (c >=
'a' && c <=
'z')
109 return (c -
'a') +
'A';
110 unsigned char uc = c;
112 case oe:
return (
char)OE;
113 case ue:
return (
char)UE;
114 case ae:
return (
char)AE;
122 for (
unsigned int i = 0; i < s.size(); ++i)
127std::string
to_snake_case(
const std::string& _s,
bool separate_at_upper_case) {
129 bool last_was_alpha =
false;
130 bool last_was_upper =
true;
132 bool is_alpha =
false;
136 if(std::isalnum(c)) {
138 is_upper = std::isupper(c);
139 if(separate_at_upper_case && !last_was_upper && is_upper)
142 }
else if(last_was_alpha) {
146 last_was_alpha = is_alpha;
147 last_was_upper = is_upper;
149 if(!s.empty() && s.back() ==
'_')
156 s.reserve(_s.size());
157 bool capitalize_next =
false;
160 capitalize_next =
true;
163 capitalize_next =
false;
171 s.reserve(_s.size());
173 c = c ==
'_' ?
'-' : c;
194 bool capitalize_next =
false;
197 capitalize_next =
true;
201 capitalize_next =
false;
209std::string&
remove(std::string& s,
char c)
211 s.erase(std::remove(s.begin(), s.end(), c), s.end());
219 std::remove_copy(s.begin(), s.end(), std::back_inserter(r), c);
226 for (
unsigned int i=0; i<_s.size(); ++i) {
227 switch ((
unsigned char)s[i]) {
228 case AE: s +=
"Ae";
break;
229 case OE: s +=
"Oe";
break;
230 case UE: s +=
"Ue";
break;
231 case ae: s +=
"ae";
break;
232 case oe: s +=
"oe";
break;
233 case ue: s +=
"ue";
break;
234 case ss: s +=
"ss";
break;
235 default : s += _s[i];
break;
241unsigned int replace(std::string& s,
char c1,
char c2)
243 unsigned int count = 0;
244 for (
unsigned int i=0; i<s.size(); ++i) {
253unsigned int replace(std::string& _s,
const std::string& s1,
const std::string& s2)
257 size_t l = _s.size();
258 size_t l1 = s1.size();
261 size_t l2 = s2.size();
264 for (
size_t pos = 0; pos <= l - l1; ++pos) {
267 if (_s[pos+i] != s1[i])
275 _s = _s.substr(0, pos) + s2 + _s.substr(pos+l1);
290 for (
unsigned int i = 0; i < s.size(); ++i) {
292 case '\a' : r +=
"\\a";
break;
293 case '\b' : r +=
"\\b";
break;
294 case '\f' : r +=
"\\f";
break;
295 case '\n' : r +=
"\\n";
break;
296 case '\r' : r +=
"\\r";
break;
297 case '\t' : r +=
"\\t";
break;
298 case '\v' : r +=
"\\v";
break;
299 case '\'' : r +=
"\\'";
break;
300 case '"' : r +=
"\\\"";
break;
301 case '\\' : r +=
"\\\\";
break;
312 for (
unsigned int i = 0; i < s.size(); ++i) {
314 if (i+1 < s.size()) {
317 case 'a' : r +=
'\a';
break;
318 case 'b' : r +=
'\b';
break;
319 case 'f' : r +=
'\f';
break;
320 case 'n' : r +=
'\n';
break;
321 case 'r' : r +=
'\r';
break;
322 case 't' : r +=
'\t';
break;
323 case 'v' : r +=
'\v';
break;
324 case '\'' : r +=
'\'';
break;
325 case '\"' : r +=
'\"';
break;
326 case '\\' : r +=
'\\';
break;
327 case '?' : r +=
'\?';
break;
337 r += char((s[i]-
'0')*64+(s[i+1]-
'0')*8+(s[i+2]-
'0'));
344 if (i+2 < s.size()) {
347 c += (s[i+1]-
'0')*16;
360 default: r += s[i];
break;
375 return s.find_first_of(c) != std::string::npos;
378bool is_element(
const std::string& e,
const std::string& s,
char sep)
383std::string
get_element(
const std::string& s,
int element_index,
char sep)
385 size_t end_pos, start_pos = 0;
390 start_pos = end_pos + 1;
391 if (start_pos == s.size())
394 end_pos = s.find_first_of(sep, start_pos);
395 if (end_pos == std::string::npos) {
399 }
while (ei < element_index);
400 if (ei < element_index)
402 return s.substr(start_pos, end_pos - start_pos);
407 if (e.empty() && s.empty())
411 bool at_start =
true;
415 for (
size_t i = 0; i<n; ++i) {
417 if (k == e.size() && match)
426 if (k == e.size() || s[i] != e[k])
433 if (k == e.size() && match)
438#if __cplusplus >= 201703L
440 inline const bool char_is_zero_or_whitespace (
const char ch) {
441 return ch == 0 || ch ==
'\r' || ch ==
'\n' || ch ==
' ' || ch ==
'\t';
444 inline const bool from_chars_success (
const std::from_chars_result &r,
const char *end_char) {
445 return r.ec == std::errc() && (r.ptr == end_char || char_is_zero_or_whitespace(*r.ptr));
449bool is_integer(
const char* begin,
const char* end,
int& value)
454#if __cplusplus >= 201703L
455 return from_chars_success(std::from_chars(begin, end, value), end);
458 while (begin < end && *begin ==
' ')
461 if (end-begin>2 && begin[0] ==
'0' &&
to_upper(begin[1]) ==
'X') {
462 int new_value = 0, b = 1;
464 for (p = end; p>begin+2; b *= 16) {
467 new_value += (int)(*p -
'0')*b;
470 if (c >=
'A' && c <=
'F')
471 new_value += (int)(c -
'A' + 10)*b;
479 int new_value = 0, b = 1;
481 for (p = end; p>begin; b *= 10) {
484 new_value += (
int)(*p -
'0')*b;
487 new_value = -new_value;
505 return is_integer(&s[0], &s[0]+s.size(), value);
508bool is_double(
const char* begin,
const char* end,
double& value)
513#if __cplusplus >= 201703L
514 return from_chars_success(std::from_chars(begin, end, value), end);
516 bool found_digit =
false;
519 bool sign_may_follow =
true;
520 const char* p = begin;
521 while (p < end && *p ==
' ')
536 sign_may_follow =
false;
540 if (!sign_may_follow)
542 sign_may_follow =
false;
547 sign_may_follow =
false;
553 sign_may_follow =
true;
561 value = atof(std::string(begin,end-begin).c_str());
568 return is_double(&s[0], &s[0]+s.size(), value);
572bool is_year(
const char* begin,
const char* end,
unsigned short& year,
bool short_allowed)
575 unsigned int size = (
unsigned int) (end-begin);
576 if ((size == 2 && short_allowed) ||
584bool is_year(
const std::string& s,
unsigned short& year,
bool short_allowed)
586 return is_year(&s[0], &s[0]+s.size(), year, short_allowed);
589bool find_name(
const std::string& s,
const char* names[],
int& idx)
602bool is_month(
const char* begin,
const char* end,
unsigned char& month)
604 static const char* months_short[] = {
605 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec", 0
607 static const char* months_english[] = {
608 "january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december", 0
610 static const char* months_german[] = {
611 "januar",
"februar",
"maerz",
"april",
"mai",
"juni",
"juli",
"august",
"september",
"oktober",
"november",
"dezember", 0
615 if (i > 0 && i <= 12) {
628bool is_month(
const std::string& s,
unsigned char& month)
630 return is_month(&s[0], &s[0]+s.size(), month);
637 size_t end = s.size();
640 size_t pos = s.find_first_of(
':');
641 if (pos == std::string::npos)
644 if (!(
is_integer(&s[0], &s[pos], i) && i >= 0 && i < 24))
646 t.h = (
unsigned char) i;
650 size_t pos2 = s.find_first_of(
':', pos);
651 size_t pos3 = pos2+1;
652 if (pos2 == std::string::npos)
654 if (!(
is_integer(&s[pos], &s[pos2], i) && i >= 0 && i < 60))
656 t.minutes = (
unsigned char) i;
659 *new_end = &s[0]+pos3;
663 while (pos2 < end &&
is_digit(s[pos2]))
665 if (!(
is_integer(&s[pos], &s[pos2], i) && i >= 0 && i < 60))
669 *new_end = &s[0]+pos2;
677 size_t end = s.size();
680 size_t pos = s.find_first_of(
'.');
681 if (pos == std::string::npos)
684 if (!(
is_integer(&s[0], &s[pos], i) && i > 0 && i < 32))
686 d.day = (
unsigned char)i;
689 *new_end = &s[0]+pos+1;
693 size_t pos2 = s.find_first_of(
'.', pos);
694 if (pos2 == std::string::npos)
696 if (!
is_month(&s[pos], &s[pos2], d.month))
700 *new_end = &s[0]+pos2+1;
704 while (pos2 < end &&
is_digit(s[pos2]))
706 if (!
is_year(&s[pos],&s[pos2],d.year))
709 *new_end = &s[0]+pos2;
715 std::string s(begin,end-begin);
718 *new_end = end + (*new_end - (&s[0]+s.length()));
726 std::string s(begin,end-begin);
729 *new_end = end + (*new_end - (&s[0]+s.length()));
735bool is_url(
const std::string& s,
const char** end)
737 if (s.substr(0,8) ==
"https://" ||
738 s.substr(0,7) ==
"http://" ||
739 s.substr(0,6) ==
"ftp://" ||
740 s.substr(0,6) ==
"smb://" ||
741 s.substr(0,6) ==
"svn://" ||
742 s.substr(0,7) ==
"file://") {
744 *end = &s[s.length()-1];
754bool is_url(
const char* begin,
const char* end,
const char** new_end)
756 std::string s(begin,end-begin);
759 *new_end = end + (*new_end - (&s[0]+s.length()));
767 while (begin < end &&
is_space(*begin))
774 while (begin < end &&
is_space(*(end-1)))
779std::string&
ltrim(std::string& str,
const std::string& chars)
781 str.erase(0, str.find_first_not_of(chars));
785std::string&
rtrim(std::string& str,
const std::string& chars)
787 str.erase(str.find_last_not_of(chars) + 1);
791std::string&
trim(std::string& str,
const std::string& chars)
796std::string
ltrim(
const std::string& str,
const std::string& chars)
799 s.erase(0, str.find_first_not_of(chars));
803std::string
rtrim(
const std::string& str,
const std::string& chars)
806 s.erase(str.find_last_not_of(chars) + 1);
810std::string
trim(
const std::string& str,
const std::string& chars)
817 std::replace_if(str.begin(), str.end(),
is_space,
' ');
820 std::string::iterator new_end = std::unique(str.begin(), str.end(), [](
char lhs,
char rhs) {
821 return (lhs == rhs) && lhs ==
' ';
823 str.erase(new_end, str.end());
827std::string
join(
const std::vector<std::string>& strs,
const std::string& sep,
bool trailing_sep)
829 std::string res =
"";
830 for(
size_t i = 0; i < strs.size(); ++i) {
831 const std::string& str = strs[i];
833 if((i + 1) < strs.size() || trailing_sep)
842 std::vector<int> v0(s2.length() + 1);
843 std::vector<int> v1(s2.length() + 1);
848 for (
size_t i = 0; i <= s2.length(); ++i) {
852 for (
size_t i = 0; i < s1.length(); ++i) {
860 for (
size_t j = 0; j < s2.length(); ++j) {
862 int deletion_cost = v0[j + 1] + 1;
863 int insertion_cost = v1[j] + 1;
864 int substitution_cost = 0;
866 substitution_cost = v0[j];
868 substitution_cost = v0[j] + 1;
870 v1[j + 1] = std::min(std::min(deletion_cost, insertion_cost), substitution_cost);
878 return v0[s2.length()];
bool is_digit(char c)
check if char is a digit
std::string join(const InputIt first, const InputIt last, const std::string &separator, bool trailing_separator=false)
Concatenate elements in the range [first, last) to a std::string.
unsigned int replace(std::string &s, char c1, char c2)
replace char c1 with c2 in the given string _s and return number of replacements
std::string to_hex(uint8_t v, bool use_upper_case)
convert to hex
std::string get_element(const std::string &s, int element_index, char sep)
interpret s as a list separated by sep and return the element with the given element index.
bool is_url(const std::string &s, const char **end)
check and extract end of valid url from string s
std::string condense_to_line(std::string str)
replace all newlines and white spaces with single spaces
std::string & rtrim(std::string &str, const std::string &chars)
trim white space or other characters from end of string
std::string interpret_special(const std::string &s)
interprets the C++ special characters \a, \b, \f, \n, \r, \t, \v, \\', \", \\, \?,...
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
std::string escape_special(const std::string &s)
escapes the C++ special characters \a, \b, \f, \n, \r, \t, \v, \\', \", \\, \?
bool is_month(const char *begin, const char *end, unsigned char &month)
check and extract month from string token [begin, end]
std::string & trim(std::string &str, const std::string &chars)
trim white space or other characters from start and end of string
std::string snake_case_to_pascal_case(const std::string &_s)
convert string from "snake_case" to "PascalCase"
std::string to_snake_case(const std::string &_s, bool separate_at_upper_case)
convert string to "snake_case" by trimming leading and trailing whitespaces and underscores,...
bool is_year(const char *begin, const char *end, unsigned short &year, bool short_allowed)
check and extract year from string token [begin, end]
std::string & ltrim(std::string &str, const std::string &chars)
trim white space or other characters from start of string
bool is_url_special(char c)
check if char is a special character from an url
std::string snake_case_to_camel_case(const std::string &_s)
convert string from "snake_case" to "camelCase"
std::string snake_case_to_capitalized_case(const std::string &_s)
convert string from "snake_case" to "Capitalized Case"
char to_lower(char c)
convert char to lower case
bool is_date(const std::string &s, cgv::utils::date &d, const char **new_end)
check and extract date from string s
char to_upper(char c)
convert char to upper case
std::string remove_copy(const std::string &s, char c)
return a copy of the given string s with all occurences of char removed
bool is_space(char c)
check if char is a whitespace
bool find_name(const std::string &s, const char *names[], int &idx)
check if string s is contained in the given array of names and in case of success store name index in...
std::string replace_special(const std::string &_s)
replaces the german special characters ä,ö,ü,ß,Ä,Ö,Ü
bool is_letter(char c)
check if char is a letter
bool is_double(const char *begin, const char *end, double &value)
check if the text range (begin,end( defines a double value. If yes, store the value in the passed ref...
bool is_time(const std::string &s, cgv::utils::time &t, const char **new_end)
check and extract time from string s
bool is_element(char c, const std::string &s)
check if char c arises in string s
const char * cutoff_spaces(const char *begin, const char *end)
return new end pointer by cutting off spaces at the end
uint8_t from_hex(char c)
convert from hex character
std::string & remove(std::string &s, char c)
remove char c from the given string s and return a reference to the same string object
std::string snake_case_to_kebab_case(const std::string &_s)
convert string from "snake_case" to "kebab-case"
int get_element_index(const std::string &e, const std::string &s, char sep)
check if the string e is contained as element in the string s, which is a list separated by sep and r...
const char * skip_spaces(const char *begin, const char *end)
return new start pointer by skipping spaces at begin
std::vector< uint8_t > parse_hex_bytes(const std::string &byte_str)
parse bytes hex coded bytes
std::string snake_case_to_sentence_case(const std::string &_s)
convert string from "snake_case" to "Sentence case"
unsigned int levenshtein_distance(const std::string &s1, const std::string &s2)
compute the levenshtein distance between two strings s1 and s2
Helper functions to process strings.