cgv
Loading...
Searching...
No Matches
scan.cxx
1#include "scan.h"
2
3#include <stdlib.h>
4#include <algorithm>
5#if __cplusplus >= 201703L
6#include <charconv>
7#endif
8
9namespace cgv {
10 namespace utils {
11
12bool is_space(char c) {
13 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
14}
15
16bool is_url_special(char c) {
17 return c == '.' || c == ',' || c == ';' || c == ':';
18}
19
20bool is_digit(char c) {
21 return c >= '0' && c <= '9';
22}
23
24bool is_letter(char c)
25{
26 c = to_lower(c);
27 return c >= 'a' && c <= 'z';
28}
29
30// C++-Version:
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);
38
39char to_lower(char c)
40{
41 if (c >= 'A' && c <= 'Z')
42 return (c - 'A') + 'a';
43 unsigned char uc = c;
44 switch (uc) {
45 case OE: return (char)oe;
46 case UE: return (char)ue;
47 case AE: return (char)ae;
48 default: return c;
49 }
50}
51
52std::string to_hex(uint8_t v, bool use_upper_case)
53{
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);
59}
60uint8_t from_hex(char c)
61{
62 switch (c) {
63 case '0':
64 case '1':
65 case '2':
66 case '3':
67 case '4':
68 case '5':
69 case '6':
70 case '7':
71 case '8':
72 case '9':
73 return c - '0';
74 case 'A':
75 case 'B':
76 case 'C':
77 case 'D':
78 case 'E':
79 case 'F':
80 return 10 + (c - 'A');
81 case 'a':
82 case 'b':
83 case 'c':
84 case 'd':
85 case 'e':
86 case 'f':
87 return 10 + (c - 'a');
88 }
89 return 0;
90}
91std::vector<uint8_t> parse_hex_bytes(const std::string& byte_str)
92{
93 std::vector<uint8_t> bytes;
94 for (size_t i = 0; i < byte_str.size(); i += 2)
95 bytes.push_back(16 * from_hex(byte_str[i]) + from_hex(byte_str[i + 1]));
96 return bytes;
97}
98std::string to_lower(const std::string& _s)
99{
100 std::string s(_s);
101 for (unsigned int i = 0; i < s.size(); ++i)
102 s[i] = to_lower(s[i]);
103 return s;
104}
105
106char to_upper(char c)
107{
108 if (c >= 'a' && c <= 'z')
109 return (c - 'a') + 'A';
110 unsigned char uc = c;
111 switch (uc) {
112 case oe: return (char)OE;
113 case ue: return (char)UE;
114 case ae: return (char)AE;
115 default: return c;
116 }
117}
118
119std::string to_upper(const std::string& _s)
120{
121 std::string s(_s);
122 for (unsigned int i = 0; i < s.size(); ++i)
123 s[i] = to_upper(s[i]);
124 return s;
125}
126
127std::string to_snake_case(const std::string& _s, bool separate_at_upper_case) {
128 std::string s;
129 bool last_was_alpha = false;
130 bool last_was_upper = true;
131 for(char c : _s) {
132 bool is_alpha = false;
133
134 int is_upper = true;
135
136 if(std::isalnum(c)) {
137 is_alpha = true;
138 is_upper = std::isupper(c);
139 if(separate_at_upper_case && !last_was_upper && is_upper)
140 s += '_';
141 s += cgv::utils::to_lower(c);
142 } else if(last_was_alpha) {
143 s += '_';
144 }
145
146 last_was_alpha = is_alpha;
147 last_was_upper = is_upper;
148 }
149 if(!s.empty() && s.back() == '_')
150 s.pop_back();
151 return s;
152}
153
154std::string snake_case_to_camel_case(const std::string& _s) {
155 std::string s;
156 s.reserve(_s.size());
157 bool capitalize_next = false;
158 for(char c : _s) {
159 if(c == '_') {
160 capitalize_next = true;
161 } else {
162 s += capitalize_next ? cgv::utils::to_upper(c) : c;
163 capitalize_next = false;
164 }
165 }
166 return s;
167}
168
169std::string snake_case_to_kebab_case(const std::string& _s) {
170 std::string s = _s;
171 s.reserve(_s.size());
172 for(char& c : s)
173 c = c == '_' ? '-' : c;
174 return s;
175}
176
177std::string snake_case_to_pascal_case(const std::string& _s) {
178 std::string s = snake_case_to_camel_case(_s);
179 if(!s.empty())
180 s[0] = cgv::utils::to_upper(s[0]);
181 return s;
182}
183
184std::string snake_case_to_sentence_case(const std::string& _s) {
185 std::string s = _s;
186 cgv::utils::replace(s, '_', ' ');
187 if(!s.empty())
188 s[0] = cgv::utils::to_upper(s[0]);
189 return s;
190}
191
192std::string snake_case_to_capitalized_case(const std::string& _s) {
193 std::string s = _s;
194 bool capitalize_next = false;
195 for(char& c : s) {
196 if(c == '_') {
197 capitalize_next = true;
198 c = ' ';
199 } else {
200 c = capitalize_next ? cgv::utils::to_upper(c) : c;
201 capitalize_next = false;
202 }
203 }
204 if(!s.empty())
205 s[0] = cgv::utils::to_upper(s[0]);
206 return s;
207}
208
209std::string& remove(std::string& s, char c)
210{
211 s.erase(std::remove(s.begin(), s.end(), c), s.end());
212 return s;
213}
214
215
216std::string remove_copy(const std::string& s, char c)
217{
218 std::string r;
219 std::remove_copy(s.begin(), s.end(), std::back_inserter(r), c);
220 return r;
221}
222
223std::string replace_special(const std::string& _s)
224{
225 std::string s;
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;
236 }
237 }
238 return s;
239}
240
241unsigned int replace(std::string& s, char c1, char c2)
242{
243 unsigned int count = 0;
244 for (unsigned int i=0; i<s.size(); ++i) {
245 if (s[i] == c1) {
246 s[i] = c2;
247 ++count;
248 }
249 }
250 return count;
251}
252
253unsigned int replace(std::string& _s, const std::string& s1, const std::string& s2)
254{
255 if (s1.empty())
256 return 0;
257 size_t l = _s.size();
258 size_t l1 = s1.size();
259 if (l1 > l)
260 return 0;
261 size_t l2 = s2.size();
262 // count number of replacements in n
263 size_t n = 0;
264 for (size_t pos = 0; pos <= l - l1; ++pos) {
265 size_t i;
266 for (i=0; i<l1; ++i)
267 if (_s[pos+i] != s1[i])
268 break;
269 if (i == l1) {
270 if (l1 == l2) {
271 for (i=0; i<l1; ++i)
272 _s[pos+i] = s2[i];
273 }
274 else {
275 _s = _s.substr(0, pos) + s2 + _s.substr(pos+l1);
276 l = _s.size();
277 }
278 pos += l2;
279 ++n;
280 if (l1 > l)
281 return (unsigned)n;
282 }
283 }
284 return (unsigned)n;
285}
286
287std::string escape_special(const std::string& s)
288{
289 std::string r;
290 for (unsigned int i = 0; i < s.size(); ++i) {
291 switch (s[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;
302 default:
303 r += s[i];
304 }
305 }
306 return r;
307}
308
309std::string interpret_special(const std::string& s)
310{
311 std::string r;
312 for (unsigned int i = 0; i < s.size(); ++i) {
313 if (s[i] == '\\') {
314 if (i+1 < s.size()) {
315 ++i;
316 switch (s[i]) {
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;
328 case '0':
329 case '1':
330 case '2':
331 case '3':
332 case '4':
333 case '5':
334 case '6':
335 case '7':
336 if (i+2 < s.size() && is_digit(s[i+1]) && is_digit(s[i+2]) ) {
337 r += char((s[i]-'0')*64+(s[i+1]-'0')*8+(s[i+2]-'0'));
338 i += 2;
339 }
340 else
341 r += s[i];
342 break;
343 case 'x' :
344 if (i+2 < s.size()) {
345 char c = 0;
346 if (is_digit(s[i+1]))
347 c += (s[i+1]-'0')*16;
348 else
349 c += (to_lower(s[i+1])-'a')*16;
350 if (is_digit(s[i+2]))
351 c += s[i+2]-'0';
352 else
353 c += to_lower(s[i+2])-'a';
354 r += c;
355 i += 2;
356 }
357 else
358 r += s[i];
359 break;
360 default: r += s[i]; break;
361 }
362 }
363 else
364 r += s[i];
365 }
366 else
367 r += s[i];
368 }
369 return r;
370}
371
372
373bool is_element(char c, const std::string& s)
374{
375 return s.find_first_of(c) != std::string::npos;
376}
377
378bool is_element(const std::string& e, const std::string& s, char sep)
379{
380 return get_element_index(e,s,sep) != -1;
381}
382
383std::string get_element(const std::string& s, int element_index, char sep)
384{
385 size_t end_pos, start_pos = 0;
386 int ei = -1;
387 do {
388 ++ei;
389 if (ei > 0) {
390 start_pos = end_pos + 1;
391 if (start_pos == s.size())
392 return "";
393 }
394 end_pos = s.find_first_of(sep, start_pos);
395 if (end_pos == std::string::npos) {
396 end_pos = s.size();
397 break;
398 }
399 } while (ei < element_index);
400 if (ei < element_index)
401 return "";
402 return s.substr(start_pos, end_pos - start_pos);
403}
404
405int get_element_index(const std::string& e, const std::string& s, char sep)
406{
407 if (e.empty() && s.empty())
408 return 0;
409
410 size_t n = s.size();
411 bool at_start = true;
412 int idx = 0;
413 unsigned k = 0;
414 bool match = true;
415 for (size_t i = 0; i<n; ++i) {
416 if (s[i] == sep) {
417 if (k == e.size() && match)
418 return idx;
419 k = 0;
420 ++idx;
421 match = true;
422 }
423 else {
424 at_start = false;
425 if (match) {
426 if (k == e.size() || s[i] != e[k])
427 match = false;
428 else
429 ++k;
430 }
431 }
432 }
433 if (k == e.size() && match)
434 return idx;
435 return -1;
436}
437
438#if __cplusplus >= 201703L
439 // We will be using std::from_chars below for parsing, this provides the whitespace check we need there
440 inline const bool char_is_zero_or_whitespace (const char ch) {
441 return ch == 0 || ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t';
442 }
443 // This is the logic we're using to test whether a from_chars conversion was successful
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));
446 }
447#endif
448
449bool is_integer(const char* begin, const char* end, int& value)
450{
451 if (begin == end)
452 return false;
453
454#if __cplusplus >= 201703L
455 return from_chars_success(std::from_chars(begin, end, value), end);
456#else
457 // skip trailing spaces
458 while (begin < end && *begin == ' ')
459 ++begin;
460 // check for hexadecimal case
461 if (end-begin>2 && begin[0] == '0' && to_upper(begin[1]) == 'X') {
462 int new_value = 0, b = 1;
463 const char* p;
464 for (p = end; p>begin+2; b *= 16) {
465 --p;
466 if (is_digit(*p))
467 new_value += (int)(*p - '0')*b;
468 else {
469 char c = to_upper(*p);
470 if (c >= 'A' && c <= 'F')
471 new_value += (int)(c - 'A' + 10)*b;
472 else
473 return false;
474 }
475 }
476 value = new_value;
477 return true;
478 }
479 int new_value = 0, b = 1;
480 const char* p;
481 for (p = end; p>begin; b *= 10) {
482 --p;
483 if (is_digit(*p))
484 new_value += (int)(*p - '0')*b;
485 else {
486 if (*p == '-') {
487 new_value = -new_value;
488 break;
489 }
490 if (*p != '+')
491 return false;
492 break;
493 }
494 }
495 if (p == begin) {
496 value = new_value;
497 return true;
498 }
499 return false;
500#endif
501}
502
503bool is_integer(const std::string& s, int& value)
504{
505 return is_integer(&s[0], &s[0]+s.size(), value);
506}
507
508bool is_double(const char* begin, const char* end, double& value)
509{
510 if (begin == end)
511 return false;
512
513#if __cplusplus >= 201703L
514 return from_chars_success(std::from_chars(begin, end, value), end);
515#else
516 bool found_digit = false;
517 int nr_dots = 0;
518 int nr_exp = 0;
519 bool sign_may_follow = true;
520 const char* p = begin;
521 while (p < end && *p == ' ')
522 ++p;
523 for (; p<end; ++p) {
524 switch (*p) {
525 case '0' :
526 case '1' :
527 case '2' :
528 case '3' :
529 case '4' :
530 case '5' :
531 case '6' :
532 case '7' :
533 case '8' :
534 case '9' :
535 found_digit = true;
536 sign_may_follow = false;
537 break;
538 case '+' :
539 case '-' :
540 if (!sign_may_follow)
541 return false;
542 sign_may_follow = false;
543 break;
544 case '.' :
545 if (++nr_dots > 1)
546 return false;
547 sign_may_follow = false;
548 break;
549 case 'e' :
550 case 'E' :
551 if (++nr_exp > 1)
552 return false;
553 sign_may_follow = true;
554 break;
555 default:
556 return false;
557 }
558 }
559 if (!found_digit)
560 return false;
561 value = atof(std::string(begin,end-begin).c_str());
562 return true;
563#endif
564}
565
566bool is_double(const std::string& s, double& value)
567{
568 return is_double(&s[0], &s[0]+s.size(), value);
569}
570
571
572bool is_year(const char* begin, const char* end, unsigned short& year, bool short_allowed)
573{
574 int i;
575 unsigned int size = (unsigned int) (end-begin);
576 if ((size == 2 && short_allowed) ||
577 ((size == 4) && is_integer(begin, end, i))) {
578 year = i;
579 return true;
580 }
581 return false;
582}
583
584bool is_year(const std::string& s, unsigned short& year, bool short_allowed)
585{
586 return is_year(&s[0], &s[0]+s.size(), year, short_allowed);
587}
588
589bool find_name(const std::string& s, const char* names[], int& idx)
590{
591 unsigned int i=0;
592 while (names[i]) {
593 if (s == names[i]) {
594 idx = i;
595 return true;
596 }
597 ++i;
598 }
599 return false;
600}
601
602bool is_month(const char* begin, const char* end, unsigned char& month)
603{
604 static const char* months_short[] = {
605 "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", 0
606 };
607 static const char* months_english[] = {
608 "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", 0
609 };
610 static const char* months_german[] = {
611 "januar", "februar", "maerz", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "dezember", 0
612 };
613 int i;
614 if (is_integer(begin,end,i)) {
615 if (i > 0 && i <= 12) {
616 month = i+1;
617 return true;
618 }
619 }
620 std::string s = to_lower(replace_special(std::string(begin,end-begin)));
621 if (find_name(s, months_short, i) || find_name(s, months_english, i) || find_name(s, months_german, i) ) {
622 month = i+1;
623 return true;
624 }
625 return false;
626}
627
628bool is_month(const std::string& s, unsigned char& month)
629{
630 return is_month(&s[0], &s[0]+s.size(), month);
631}
632
633bool is_time(const std::string& s, cgv::utils::time& t, const char **new_end)
634{
635 if (s.size() == 0)
636 return false;
637 size_t end = s.size();
638 while (end > 0 && is_url_special(s[end-1]))
639 --end;
640 size_t pos = s.find_first_of(':');
641 if (pos == std::string::npos)
642 return false;
643 int i;
644 if (!(is_integer(&s[0], &s[pos], i) && i >= 0 && i < 24))
645 return false;
646 t.h = (unsigned char) i;
647 if (pos >= end)
648 return false;
649 ++pos;
650 size_t pos2 = s.find_first_of(':', pos);
651 size_t pos3 = pos2+1;
652 if (pos2 == std::string::npos)
653 pos3 = pos2 = end;
654 if (!(is_integer(&s[pos], &s[pos2], i) && i >= 0 && i < 60))
655 return false;
656 t.minutes = (unsigned char) i;
657 if (pos2 >= end) {
658 if (new_end)
659 *new_end = &s[0]+pos3;
660 return true;
661 }
662 pos = ++pos2;
663 while (pos2 < end && is_digit(s[pos2]))
664 ++pos2;
665 if (!(is_integer(&s[pos], &s[pos2], i) && i >= 0 && i < 60))
666 return false;
667 t.sec = i;
668 if (new_end)
669 *new_end = &s[0]+pos2;
670 return true;
671}
672
673bool is_date(const std::string& s, cgv::utils::date& d, const char **new_end)
674{
675 if (s.size() == 0)
676 return false;
677 size_t end = s.size();
678 while (end > 0 && is_url_special(s[end-1]))
679 --end;
680 size_t pos = s.find_first_of('.');
681 if (pos == std::string::npos)
682 return false;
683 int i;
684 if (!(is_integer(&s[0], &s[pos], i) && i > 0 && i < 32))
685 return false;
686 d.day = (unsigned char)i;
687 if (pos >= end) {
688 if (new_end)
689 *new_end = &s[0]+pos+1;
690 return true;
691 }
692 ++pos;
693 size_t pos2 = s.find_first_of('.', pos);
694 if (pos2 == std::string::npos)
695 return false;
696 if (!is_month(&s[pos], &s[pos2], d.month))
697 return false;
698 if (pos2 >= end) {
699 if (new_end)
700 *new_end = &s[0]+pos2+1;
701 return true;
702 }
703 pos = ++pos2;
704 while (pos2 < end && is_digit(s[pos2]))
705 ++pos2;
706 if (!is_year(&s[pos],&s[pos2],d.year))
707 return false;
708 if (new_end)
709 *new_end = &s[0]+pos2;
710 return true;
711}
712
713bool is_time(const char* begin, const char* end, cgv::utils::time& t, const char **new_end)
714{
715 std::string s(begin,end-begin);
716 if (is_time(s, t, new_end)) {
717 if (new_end)
718 *new_end = end + (*new_end - (&s[0]+s.length()));
719 return true;
720 }
721 return false;
722}
723
724bool is_date(const char* begin, const char* end, cgv::utils::date& d, const char **new_end)
725{
726 std::string s(begin,end-begin);
727 if (is_date(s, d, new_end)) {
728 if (new_end)
729 *new_end = end + (*new_end - (&s[0]+s.length()));
730 return true;
731 }
732 return false;
733}
734
735bool is_url(const std::string& s, const char** end)
736{
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://") {
743 if (end) {
744 *end = &s[s.length()-1];
745 while (is_url_special(**end))
746 --*end;
747 ++*end;
748 }
749 return true;
750 }
751 return false;
752}
753
754bool is_url(const char* begin, const char* end, const char** new_end)
755{
756 std::string s(begin,end-begin);
757 if (is_url(s, new_end)) {
758 if (new_end)
759 *new_end = end + (*new_end - (&s[0]+s.length()));
760 return true;
761 }
762 return false;
763}
764
765const char* skip_spaces(const char* begin, const char* end)
766{
767 while (begin < end && is_space(*begin))
768 ++begin;
769 return begin;
770}
771
772const char* cutoff_spaces(const char* begin, const char* end)
773{
774 while (begin < end && is_space(*(end-1)))
775 --end;
776 return end;
777}
778
779std::string& ltrim(std::string& str, const std::string& chars)
780{
781 str.erase(0, str.find_first_not_of(chars));
782 return str;
783}
784
785std::string& rtrim(std::string& str, const std::string& chars)
786{
787 str.erase(str.find_last_not_of(chars) + 1);
788 return str;
789}
790
791std::string& trim(std::string& str, const std::string& chars)
792{
793 return ltrim(rtrim(str, chars), chars);
794}
795
796std::string ltrim(const std::string& str, const std::string& chars)
797{
798 std::string s = str;
799 s.erase(0, str.find_first_not_of(chars));
800 return s;
801}
802
803std::string rtrim(const std::string& str, const std::string& chars)
804{
805 std::string s = str;
806 s.erase(str.find_last_not_of(chars) + 1);
807 return s;
808}
809
810std::string trim(const std::string& str, const std::string& chars)
811{
812 return ltrim(rtrim(str, chars), chars);
813}
814
815std::string condense_to_line(std::string str)
816{
817 std::replace_if(str.begin(), str.end(), is_space, ' ');
818 cgv::utils::trim(str);
819 // replace all consecutive spaces with a single space
820 std::string::iterator new_end = std::unique(str.begin(), str.end(), [](char lhs, char rhs) {
821 return (lhs == rhs) && lhs == ' ';
822 });
823 str.erase(new_end, str.end());
824 return str;
825}
826
827std::string join(const std::vector<std::string>& strs, const std::string& sep, bool trailing_sep)
828{
829 std::string res = "";
830 for(size_t i = 0; i < strs.size(); ++i) {
831 const std::string& str = strs[i];
832 res += str;
833 if((i + 1) < strs.size() || trailing_sep)
834 res += sep;
835 }
836 return res;
837}
838
839unsigned int levenshtein_distance(const std::string& s1, const std::string& s2)
840{
841 // create two work vectors of integer distances
842 std::vector<int> v0(s2.length() + 1);
843 std::vector<int> v1(s2.length() + 1);
844
845 // initialize v0 (the previous row of distances)
846 // this row is A[0][i]: edit distance from an empty s to t;
847 // that distance is the number of characters to append to s to make t.
848 for (size_t i = 0; i <= s2.length(); ++i) {
849 v0[i] = int(i);
850 }
851
852 for (size_t i = 0; i < s1.length(); ++i) {
853 // calculate v1 (current row distances) from the previous row v0
854
855 // first element of v1 is A[i + 1][0]
856 // edit distance is delete (i + 1) chars from s to match empty t
857 v1[0] = int(i + 1);
858
859 // use formula to fill in the rest of the row
860 for (size_t j = 0; j < s2.length(); ++j) {
861 // calculating costs for A[i + 1][j + 1]
862 int deletion_cost = v0[j + 1] + 1;
863 int insertion_cost = v1[j] + 1;
864 int substitution_cost = 0;
865 if (s1[i] == s2[j])
866 substitution_cost = v0[j];
867 else
868 substitution_cost = v0[j] + 1;
869
870 v1[j + 1] = std::min(std::min(deletion_cost, insertion_cost), substitution_cost);
871 }
872
873 // copy v1 (current row) to v0 (previous row) for next iteration
874 // since data in v1 is always invalidated, a swap without copy could be more efficient
875 std::swap(v0, v1);
876 }
877 // after the last swap, the results of v1 are now in v0
878 return v0[s2.length()];
879}
880
881 }
882}
bool is_digit(char c)
check if char is a digit
Definition scan.cxx:20
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.
Definition algorithm.h:148
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
Definition scan.cxx:241
std::string to_hex(uint8_t v, bool use_upper_case)
convert to hex
Definition scan.cxx:52
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.
Definition scan.cxx:383
bool is_url(const std::string &s, const char **end)
check and extract end of valid url from string s
Definition scan.cxx:735
std::string condense_to_line(std::string str)
replace all newlines and white spaces with single spaces
Definition scan.cxx:815
std::string & rtrim(std::string &str, const std::string &chars)
trim white space or other characters from end of string
Definition scan.cxx:785
std::string interpret_special(const std::string &s)
interprets the C++ special characters \a, \b, \f, \n, \r, \t, \v, \\', \", \\, \?,...
Definition scan.cxx:309
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...
Definition scan.cxx:449
std::string escape_special(const std::string &s)
escapes the C++ special characters \a, \b, \f, \n, \r, \t, \v, \\', \", \\, \?
Definition scan.cxx:287
bool is_month(const char *begin, const char *end, unsigned char &month)
check and extract month from string token [begin, end]
Definition scan.cxx:602
std::string & trim(std::string &str, const std::string &chars)
trim white space or other characters from start and end of string
Definition scan.cxx:791
std::string snake_case_to_pascal_case(const std::string &_s)
convert string from "snake_case" to "PascalCase"
Definition scan.cxx:177
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,...
Definition scan.cxx:127
bool is_year(const char *begin, const char *end, unsigned short &year, bool short_allowed)
check and extract year from string token [begin, end]
Definition scan.cxx:572
std::string & ltrim(std::string &str, const std::string &chars)
trim white space or other characters from start of string
Definition scan.cxx:779
bool is_url_special(char c)
check if char is a special character from an url
Definition scan.cxx:16
std::string snake_case_to_camel_case(const std::string &_s)
convert string from "snake_case" to "camelCase"
Definition scan.cxx:154
std::string snake_case_to_capitalized_case(const std::string &_s)
convert string from "snake_case" to "Capitalized Case"
Definition scan.cxx:192
char to_lower(char c)
convert char to lower case
Definition scan.cxx:39
bool is_date(const std::string &s, cgv::utils::date &d, const char **new_end)
check and extract date from string s
Definition scan.cxx:673
char to_upper(char c)
convert char to upper case
Definition scan.cxx:106
std::string remove_copy(const std::string &s, char c)
return a copy of the given string s with all occurences of char removed
Definition scan.cxx:216
bool is_space(char c)
check if char is a whitespace
Definition scan.cxx:12
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...
Definition scan.cxx:589
std::string replace_special(const std::string &_s)
replaces the german special characters ä,ö,ü,ß,Ä,Ö,Ü
Definition scan.cxx:223
bool is_letter(char c)
check if char is a letter
Definition scan.cxx:24
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...
Definition scan.cxx:508
bool is_time(const std::string &s, cgv::utils::time &t, const char **new_end)
check and extract time from string s
Definition scan.cxx:633
bool is_element(char c, const std::string &s)
check if char c arises in string s
Definition scan.cxx:373
const char * cutoff_spaces(const char *begin, const char *end)
return new end pointer by cutting off spaces at the end
Definition scan.cxx:772
uint8_t from_hex(char c)
convert from hex character
Definition scan.cxx:60
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
Definition scan.cxx:209
std::string snake_case_to_kebab_case(const std::string &_s)
convert string from "snake_case" to "kebab-case"
Definition scan.cxx:169
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...
Definition scan.cxx:405
const char * skip_spaces(const char *begin, const char *end)
return new start pointer by skipping spaces at begin
Definition scan.cxx:765
std::vector< uint8_t > parse_hex_bytes(const std::string &byte_str)
parse bytes hex coded bytes
Definition scan.cxx:91
std::string snake_case_to_sentence_case(const std::string &_s)
convert string from "snake_case" to "Sentence case"
Definition scan.cxx:184
unsigned int levenshtein_distance(const std::string &s1, const std::string &s2)
compute the levenshtein distance between two strings s1 and s2
Definition scan.cxx:839
the cgv namespace
Definition print.h:11
Helper functions to process strings.