1 /*************************************************************************/
2 /* ustring.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #ifdef _MSC_VER
32 #define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy
33 #endif
34
35 #include "ustring.h"
36
37 #include "core/color.h"
38 #include "core/crypto/crypto_core.h"
39 #include "core/math/math_funcs.h"
40 #include "core/os/memory.h"
41 #include "core/print_string.h"
42 #include "core/translation.h"
43 #include "core/ucaps.h"
44 #include "core/variant.h"
45
46 #include <wchar.h>
47 #include <cstdint>
48
49 #ifndef NO_USE_STDLIB
50 #include <stdio.h>
51 #include <stdlib.h>
52 #endif
53
54 #if defined(MINGW_ENABLED) || defined(_MSC_VER)
55 #define snprintf _snprintf_s
56 #endif
57
58 #define MAX_DIGITS 6
59 #define UPPERCASE(m_c) (((m_c) >= 'a' && (m_c) <= 'z') ? ((m_c) - ('a' - 'A')) : (m_c))
60 #define LOWERCASE(m_c) (((m_c) >= 'A' && (m_c) <= 'Z') ? ((m_c) + ('a' - 'A')) : (m_c))
61 #define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
62 #define IS_HEX_DIGIT(m_d) (((m_d) >= '0' && (m_d) <= '9') || ((m_d) >= 'a' && (m_d) <= 'f') || ((m_d) >= 'A' && (m_d) <= 'F'))
63
64 const char CharString::_null = 0;
65 const CharType String::_null = 0;
66
is_symbol(CharType c)67 bool is_symbol(CharType c) {
68 return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' ');
69 }
70
select_word(const String & p_s,int p_col,int & r_beg,int & r_end)71 bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) {
72
73 const String &s = p_s;
74 int beg = CLAMP(p_col, 0, s.length());
75 int end = beg;
76
77 if (s[beg] > 32 || beg == s.length()) {
78
79 bool symbol = beg < s.length() && is_symbol(s[beg]);
80
81 while (beg > 0 && s[beg - 1] > 32 && (symbol == is_symbol(s[beg - 1]))) {
82 beg--;
83 }
84 while (end < s.length() && s[end + 1] > 32 && (symbol == is_symbol(s[end + 1]))) {
85 end++;
86 }
87
88 if (end < s.length())
89 end += 1;
90
91 r_beg = beg;
92 r_end = end;
93
94 return true;
95 } else {
96
97 return false;
98 }
99 }
100
101 /** STRING **/
102
operator <(const CharString & p_right) const103 bool CharString::operator<(const CharString &p_right) const {
104
105 if (length() == 0) {
106 return p_right.length() != 0;
107 }
108
109 return is_str_less(get_data(), p_right.get_data());
110 }
111
operator +=(char p_char)112 CharString &CharString::operator+=(char p_char) {
113
114 resize(size() ? size() + 1 : 2);
115 set(length(), 0);
116 set(length() - 1, p_char);
117
118 return *this;
119 }
120
get_data() const121 const char *CharString::get_data() const {
122
123 if (size())
124 return &operator[](0);
125 else
126 return "";
127 }
128
operator =(const char * p_cstr)129 CharString &CharString::operator=(const char *p_cstr) {
130
131 copy_from(p_cstr);
132 return *this;
133 }
134
copy_from(const char * p_cstr)135 void CharString::copy_from(const char *p_cstr) {
136
137 if (!p_cstr) {
138 resize(0);
139 return;
140 }
141
142 size_t len = strlen(p_cstr);
143
144 if (len == 0) {
145 resize(0);
146 return;
147 }
148
149 resize(len + 1); // include terminating null char
150
151 strcpy(ptrw(), p_cstr);
152 }
153
copy_from(const char * p_cstr)154 void String::copy_from(const char *p_cstr) {
155
156 if (!p_cstr) {
157
158 resize(0);
159 return;
160 }
161
162 int len = 0;
163 const char *ptr = p_cstr;
164 while (*(ptr++) != 0)
165 len++;
166
167 if (len == 0) {
168
169 resize(0);
170 return;
171 }
172
173 resize(len + 1); // include 0
174
175 CharType *dst = this->ptrw();
176
177 for (int i = 0; i < len + 1; i++) {
178
179 dst[i] = p_cstr[i];
180 }
181 }
182
copy_from(const CharType * p_cstr,const int p_clip_to)183 void String::copy_from(const CharType *p_cstr, const int p_clip_to) {
184
185 if (!p_cstr) {
186
187 resize(0);
188 return;
189 }
190
191 int len = 0;
192 const CharType *ptr = p_cstr;
193 while ((p_clip_to < 0 || len < p_clip_to) && *(ptr++) != 0)
194 len++;
195
196 if (len == 0) {
197
198 resize(0);
199 return;
200 }
201
202 copy_from_unchecked(p_cstr, len);
203 }
204
205 // assumes the following have already been validated:
206 // p_char != NULL
207 // p_length > 0
208 // p_length <= p_char strlen
copy_from_unchecked(const CharType * p_char,const int p_length)209 void String::copy_from_unchecked(const CharType *p_char, const int p_length) {
210 resize(p_length + 1);
211 set(p_length, 0);
212
213 CharType *dst = ptrw();
214
215 for (int i = 0; i < p_length; i++) {
216 dst[i] = p_char[i];
217 }
218 }
219
copy_from(const CharType & p_char)220 void String::copy_from(const CharType &p_char) {
221
222 resize(2);
223 set(0, p_char);
224 set(1, 0);
225 }
226
operator ==(const String & p_str) const227 bool String::operator==(const String &p_str) const {
228
229 if (length() != p_str.length())
230 return false;
231 if (empty())
232 return true;
233
234 int l = length();
235
236 const CharType *src = c_str();
237 const CharType *dst = p_str.c_str();
238
239 /* Compare char by char */
240 for (int i = 0; i < l; i++) {
241
242 if (src[i] != dst[i])
243 return false;
244 }
245
246 return true;
247 }
248
operator !=(const String & p_str) const249 bool String::operator!=(const String &p_str) const {
250
251 return !(*this == p_str);
252 }
253
operator +(const String & p_str) const254 String String::operator+(const String &p_str) const {
255
256 String res = *this;
257 res += p_str;
258 return res;
259 }
260
261 /*
262 String String::operator+(CharType p_chr) const {
263
264 String res=*this;
265 res+=p_chr;
266 return res;
267 }
268 */
operator +=(const String & p_str)269 String &String::operator+=(const String &p_str) {
270
271 if (empty()) {
272 *this = p_str;
273 return *this;
274 }
275
276 if (p_str.empty())
277 return *this;
278
279 int from = length();
280
281 resize(length() + p_str.size());
282
283 const CharType *src = p_str.c_str();
284 CharType *dst = ptrw();
285
286 set(length(), 0);
287
288 for (int i = 0; i < p_str.length(); i++)
289 dst[from + i] = src[i];
290
291 return *this;
292 }
293
operator +=(const CharType * p_str)294 String &String::operator+=(const CharType *p_str) {
295
296 *this += String(p_str);
297 return *this;
298 }
299
operator +=(CharType p_char)300 String &String::operator+=(CharType p_char) {
301
302 resize(size() ? size() + 1 : 2);
303 set(length(), 0);
304 set(length() - 1, p_char);
305
306 return *this;
307 }
308
operator +=(const char * p_str)309 String &String::operator+=(const char *p_str) {
310
311 if (!p_str || p_str[0] == 0)
312 return *this;
313
314 int src_len = 0;
315 const char *ptr = p_str;
316 while (*(ptr++) != 0)
317 src_len++;
318
319 int from = length();
320
321 resize(from + src_len + 1);
322
323 CharType *dst = ptrw();
324
325 set(length(), 0);
326
327 for (int i = 0; i < src_len; i++)
328 dst[from + i] = p_str[i];
329
330 return *this;
331 }
332
operator =(const char * p_str)333 void String::operator=(const char *p_str) {
334
335 copy_from(p_str);
336 }
337
operator =(const CharType * p_str)338 void String::operator=(const CharType *p_str) {
339
340 copy_from(p_str);
341 }
342
operator ==(const StrRange & p_str_range) const343 bool String::operator==(const StrRange &p_str_range) const {
344
345 int len = p_str_range.len;
346
347 if (length() != len)
348 return false;
349 if (empty())
350 return true;
351
352 const CharType *c_str = p_str_range.c_str;
353 const CharType *dst = &operator[](0);
354
355 /* Compare char by char */
356 for (int i = 0; i < len; i++) {
357
358 if (c_str[i] != dst[i])
359 return false;
360 }
361
362 return true;
363 }
364
operator ==(const char * p_str) const365 bool String::operator==(const char *p_str) const {
366
367 int len = 0;
368 const char *aux = p_str;
369
370 while (*(aux++) != 0)
371 len++;
372
373 if (length() != len)
374 return false;
375 if (empty())
376 return true;
377
378 int l = length();
379
380 const CharType *dst = c_str();
381
382 /* Compare char by char */
383 for (int i = 0; i < l; i++) {
384
385 if (p_str[i] != dst[i])
386 return false;
387 }
388
389 return true;
390 }
391
operator ==(const CharType * p_str) const392 bool String::operator==(const CharType *p_str) const {
393
394 int len = 0;
395 const CharType *aux = p_str;
396
397 while (*(aux++) != 0)
398 len++;
399
400 if (length() != len)
401 return false;
402 if (empty())
403 return true;
404
405 int l = length();
406
407 const CharType *dst = c_str();
408
409 /* Compare char by char */
410 for (int i = 0; i < l; i++) {
411
412 if (p_str[i] != dst[i])
413 return false;
414 }
415
416 return true;
417 }
418
operator !=(const char * p_str) const419 bool String::operator!=(const char *p_str) const {
420
421 return (!(*this == p_str));
422 }
423
operator !=(const CharType * p_str) const424 bool String::operator!=(const CharType *p_str) const {
425
426 return (!(*this == p_str));
427 }
428
operator <(const CharType * p_str) const429 bool String::operator<(const CharType *p_str) const {
430
431 if (empty() && p_str[0] == 0)
432 return false;
433 if (empty())
434 return true;
435
436 return is_str_less(c_str(), p_str);
437 }
438
operator <=(const String & p_str) const439 bool String::operator<=(const String &p_str) const {
440
441 return (*this < p_str) || (*this == p_str);
442 }
443
operator <(const char * p_str) const444 bool String::operator<(const char *p_str) const {
445
446 if (empty() && p_str[0] == 0)
447 return false;
448 if (empty())
449 return true;
450
451 return is_str_less(c_str(), p_str);
452 }
453
operator <(const String & p_str) const454 bool String::operator<(const String &p_str) const {
455
456 return operator<(p_str.c_str());
457 }
458
nocasecmp_to(const String & p_str) const459 signed char String::nocasecmp_to(const String &p_str) const {
460
461 if (empty() && p_str.empty())
462 return 0;
463 if (empty())
464 return -1;
465 if (p_str.empty())
466 return 1;
467
468 const CharType *that_str = p_str.c_str();
469 const CharType *this_str = c_str();
470
471 while (true) {
472
473 if (*that_str == 0 && *this_str == 0)
474 return 0; //we're equal
475 else if (*this_str == 0)
476 return -1; //if this is empty, and the other one is not, then we're less.. I think?
477 else if (*that_str == 0)
478 return 1; //otherwise the other one is smaller..
479 else if (_find_upper(*this_str) < _find_upper(*that_str)) //more than
480 return -1;
481 else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than
482 return 1;
483
484 this_str++;
485 that_str++;
486 }
487 }
488
casecmp_to(const String & p_str) const489 signed char String::casecmp_to(const String &p_str) const {
490
491 if (empty() && p_str.empty())
492 return 0;
493 if (empty())
494 return -1;
495 if (p_str.empty())
496 return 1;
497
498 const CharType *that_str = p_str.c_str();
499 const CharType *this_str = c_str();
500
501 while (true) {
502
503 if (*that_str == 0 && *this_str == 0)
504 return 0; //we're equal
505 else if (*this_str == 0)
506 return -1; //if this is empty, and the other one is not, then we're less.. I think?
507 else if (*that_str == 0)
508 return 1; //otherwise the other one is smaller..
509 else if (*this_str < *that_str) //more than
510 return -1;
511 else if (*this_str > *that_str) //less than
512 return 1;
513
514 this_str++;
515 that_str++;
516 }
517 }
518
naturalnocasecmp_to(const String & p_str) const519 signed char String::naturalnocasecmp_to(const String &p_str) const {
520
521 const CharType *this_str = c_str();
522 const CharType *that_str = p_str.c_str();
523
524 if (this_str && that_str) {
525
526 while (*this_str == '.' || *that_str == '.') {
527 if (*this_str++ != '.')
528 return 1;
529 if (*that_str++ != '.')
530 return -1;
531 if (!*that_str)
532 return 1;
533 if (!*this_str)
534 return -1;
535 }
536
537 while (*this_str) {
538
539 if (!*that_str)
540 return 1;
541 else if (IS_DIGIT(*this_str)) {
542
543 int64_t this_int, that_int;
544
545 if (!IS_DIGIT(*that_str))
546 return -1;
547
548 /* Compare the numbers */
549 this_int = to_int(this_str);
550 that_int = to_int(that_str);
551
552 if (this_int < that_int)
553 return -1;
554 else if (this_int > that_int)
555 return 1;
556
557 /* Skip */
558 while (IS_DIGIT(*this_str))
559 this_str++;
560 while (IS_DIGIT(*that_str))
561 that_str++;
562 } else if (IS_DIGIT(*that_str))
563 return 1;
564 else {
565 if (_find_upper(*this_str) < _find_upper(*that_str)) //more than
566 return -1;
567 else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than
568 return 1;
569
570 this_str++;
571 that_str++;
572 }
573 }
574 if (*that_str)
575 return -1;
576 }
577
578 return 0;
579 }
580
erase(int p_pos,int p_chars)581 void String::erase(int p_pos, int p_chars) {
582
583 *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
584 }
585
capitalize() const586 String String::capitalize() const {
587
588 String aux = this->camelcase_to_underscore(true).replace("_", " ").strip_edges();
589 String cap;
590 for (int i = 0; i < aux.get_slice_count(" "); i++) {
591
592 String slice = aux.get_slicec(' ', i);
593 if (slice.length() > 0) {
594
595 slice[0] = _find_upper(slice[0]);
596 if (i > 0)
597 cap += " ";
598 cap += slice;
599 }
600 }
601
602 return cap;
603 }
604
camelcase_to_underscore(bool lowercase) const605 String String::camelcase_to_underscore(bool lowercase) const {
606 const CharType *cstr = c_str();
607 String new_string;
608 const char A = 'A', Z = 'Z';
609 const char a = 'a', z = 'z';
610 int start_index = 0;
611
612 for (int i = 1; i < this->size(); i++) {
613 bool is_upper = cstr[i] >= A && cstr[i] <= Z;
614 bool is_number = cstr[i] >= '0' && cstr[i] <= '9';
615 bool are_next_2_lower = false;
616 bool is_next_lower = false;
617 bool is_next_number = false;
618 bool was_precedent_upper = cstr[i - 1] >= A && cstr[i - 1] <= Z;
619 bool was_precedent_number = cstr[i - 1] >= '0' && cstr[i - 1] <= '9';
620
621 if (i + 2 < this->size()) {
622 are_next_2_lower = cstr[i + 1] >= a && cstr[i + 1] <= z && cstr[i + 2] >= a && cstr[i + 2] <= z;
623 }
624
625 if (i + 1 < this->size()) {
626 is_next_lower = cstr[i + 1] >= a && cstr[i + 1] <= z;
627 is_next_number = cstr[i + 1] >= '0' && cstr[i + 1] <= '9';
628 }
629
630 const bool cond_a = is_upper && !was_precedent_upper && !was_precedent_number;
631 const bool cond_b = was_precedent_upper && is_upper && are_next_2_lower;
632 const bool cond_c = is_number && !was_precedent_number;
633 const bool can_break_number_letter = is_number && !was_precedent_number && is_next_lower;
634 const bool can_break_letter_number = !is_number && was_precedent_number && (is_next_lower || is_next_number);
635
636 bool should_split = cond_a || cond_b || cond_c || can_break_number_letter || can_break_letter_number;
637 if (should_split) {
638 new_string += this->substr(start_index, i - start_index) + "_";
639 start_index = i;
640 }
641 }
642
643 new_string += this->substr(start_index, this->size() - start_index);
644 return lowercase ? new_string.to_lower() : new_string;
645 }
646
get_slice_count(String p_splitter) const647 int String::get_slice_count(String p_splitter) const {
648
649 if (empty())
650 return 0;
651 if (p_splitter.empty())
652 return 0;
653
654 int pos = 0;
655 int slices = 1;
656
657 while ((pos = find(p_splitter, pos)) >= 0) {
658
659 slices++;
660 pos += p_splitter.length();
661 }
662
663 return slices;
664 }
665
get_slice(String p_splitter,int p_slice) const666 String String::get_slice(String p_splitter, int p_slice) const {
667
668 if (empty() || p_splitter.empty())
669 return "";
670
671 int pos = 0;
672 int prev_pos = 0;
673 //int slices=1;
674 if (p_slice < 0)
675 return "";
676 if (find(p_splitter) == -1)
677 return *this;
678
679 int i = 0;
680 while (true) {
681
682 pos = find(p_splitter, pos);
683 if (pos == -1)
684 pos = length(); //reached end
685
686 int from = prev_pos;
687 //int to=pos;
688
689 if (p_slice == i) {
690
691 return substr(from, pos - from);
692 }
693
694 if (pos == length()) //reached end and no find
695 break;
696 pos += p_splitter.length();
697 prev_pos = pos;
698 i++;
699 }
700
701 return ""; //no find!
702 }
703
get_slicec(CharType p_splitter,int p_slice) const704 String String::get_slicec(CharType p_splitter, int p_slice) const {
705
706 if (empty())
707 return String();
708
709 if (p_slice < 0)
710 return String();
711
712 const CharType *c = this->ptr();
713 int i = 0;
714 int prev = 0;
715 int count = 0;
716 while (true) {
717
718 if (c[i] == 0 || c[i] == p_splitter) {
719
720 if (p_slice == count) {
721
722 return substr(prev, i - prev);
723 } else if (c[i] == 0) {
724 return String();
725 } else {
726 count++;
727 prev = i + 1;
728 }
729 }
730
731 i++;
732 }
733 }
734
split_spaces() const735 Vector<String> String::split_spaces() const {
736
737 Vector<String> ret;
738 int from = 0;
739 int i = 0;
740 int len = length();
741 if (len == 0)
742 return ret;
743
744 bool inside = false;
745
746 while (true) {
747
748 bool empty = operator[](i) < 33;
749
750 if (i == 0)
751 inside = !empty;
752
753 if (!empty && !inside) {
754 inside = true;
755 from = i;
756 }
757
758 if (empty && inside) {
759
760 ret.push_back(substr(from, i - from));
761 inside = false;
762 }
763
764 if (i == len)
765 break;
766 i++;
767 }
768
769 return ret;
770 }
771
split(const String & p_splitter,bool p_allow_empty,int p_maxsplit) const772 Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {
773
774 Vector<String> ret;
775 int from = 0;
776 int len = length();
777
778 while (true) {
779
780 int end = find(p_splitter, from);
781 if (end < 0)
782 end = len;
783 if (p_allow_empty || (end > from)) {
784 if (p_maxsplit <= 0)
785 ret.push_back(substr(from, end - from));
786 else {
787
788 // Put rest of the string and leave cycle.
789 if (p_maxsplit == ret.size()) {
790 ret.push_back(substr(from, len));
791 break;
792 }
793
794 // Otherwise, push items until positive limit is reached.
795 ret.push_back(substr(from, end - from));
796 }
797 }
798
799 if (end == len)
800 break;
801
802 from = end + p_splitter.length();
803 }
804
805 return ret;
806 }
807
rsplit(const String & p_splitter,bool p_allow_empty,int p_maxsplit) const808 Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {
809
810 Vector<String> ret;
811 const int len = length();
812 int remaining_len = len;
813
814 while (true) {
815
816 if (remaining_len < p_splitter.length() || (p_maxsplit > 0 && p_maxsplit == ret.size())) {
817 // no room for another splitter or hit max splits, push what's left and we're done
818 if (p_allow_empty || remaining_len > 0) {
819 ret.push_back(substr(0, remaining_len));
820 }
821 break;
822 }
823
824 int left_edge = rfind(p_splitter, remaining_len - p_splitter.length());
825
826 if (left_edge < 0) {
827 // no more splitters, we're done
828 ret.push_back(substr(0, remaining_len));
829 break;
830 }
831
832 int substr_start = left_edge + p_splitter.length();
833 if (p_allow_empty || substr_start < remaining_len) {
834 ret.push_back(substr(substr_start, remaining_len - substr_start));
835 }
836
837 remaining_len = left_edge;
838 }
839
840 ret.invert();
841 return ret;
842 }
843
split_floats(const String & p_splitter,bool p_allow_empty) const844 Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
845
846 Vector<float> ret;
847 int from = 0;
848 int len = length();
849
850 while (true) {
851
852 int end = find(p_splitter, from);
853 if (end < 0)
854 end = len;
855 if (p_allow_empty || (end > from))
856 ret.push_back(String::to_double(&c_str()[from]));
857
858 if (end == len)
859 break;
860
861 from = end + p_splitter.length();
862 }
863
864 return ret;
865 }
866
split_floats_mk(const Vector<String> & p_splitters,bool p_allow_empty) const867 Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty) const {
868
869 Vector<float> ret;
870 int from = 0;
871 int len = length();
872
873 while (true) {
874
875 int idx;
876 int end = findmk(p_splitters, from, &idx);
877 int spl_len = 1;
878 if (end < 0) {
879 end = len;
880 } else {
881 spl_len = p_splitters[idx].length();
882 }
883
884 if (p_allow_empty || (end > from)) {
885 ret.push_back(String::to_double(&c_str()[from]));
886 }
887
888 if (end == len)
889 break;
890
891 from = end + spl_len;
892 }
893
894 return ret;
895 }
896
split_ints(const String & p_splitter,bool p_allow_empty) const897 Vector<int> String::split_ints(const String &p_splitter, bool p_allow_empty) const {
898
899 Vector<int> ret;
900 int from = 0;
901 int len = length();
902
903 while (true) {
904
905 int end = find(p_splitter, from);
906 if (end < 0)
907 end = len;
908 if (p_allow_empty || (end > from))
909 ret.push_back(String::to_int(&c_str()[from], end - from));
910
911 if (end == len)
912 break;
913
914 from = end + p_splitter.length();
915 }
916
917 return ret;
918 }
919
split_ints_mk(const Vector<String> & p_splitters,bool p_allow_empty) const920 Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty) const {
921
922 Vector<int> ret;
923 int from = 0;
924 int len = length();
925
926 while (true) {
927
928 int idx;
929 int end = findmk(p_splitters, from, &idx);
930 int spl_len = 1;
931 if (end < 0) {
932 end = len;
933 } else {
934 spl_len = p_splitters[idx].length();
935 }
936
937 if (p_allow_empty || (end > from))
938 ret.push_back(String::to_int(&c_str()[from], end - from));
939
940 if (end == len)
941 break;
942
943 from = end + spl_len;
944 }
945
946 return ret;
947 }
948
join(Vector<String> parts)949 String String::join(Vector<String> parts) {
950 String ret;
951 for (int i = 0; i < parts.size(); ++i) {
952 if (i > 0) {
953 ret += *this;
954 }
955 ret += parts[i];
956 }
957 return ret;
958 }
959
char_uppercase(CharType p_char)960 CharType String::char_uppercase(CharType p_char) {
961
962 return _find_upper(p_char);
963 }
964
char_lowercase(CharType p_char)965 CharType String::char_lowercase(CharType p_char) {
966
967 return _find_lower(p_char);
968 }
969
to_upper() const970 String String::to_upper() const {
971
972 String upper = *this;
973
974 for (int i = 0; i < upper.size(); i++) {
975
976 const CharType s = upper[i];
977 const CharType t = _find_upper(s);
978 if (s != t) // avoid copy on write
979 upper[i] = t;
980 }
981
982 return upper;
983 }
984
to_lower() const985 String String::to_lower() const {
986
987 String lower = *this;
988
989 for (int i = 0; i < lower.size(); i++) {
990
991 const CharType s = lower[i];
992 const CharType t = _find_lower(s);
993 if (s != t) // avoid copy on write
994 lower[i] = t;
995 }
996
997 return lower;
998 }
999
c_str() const1000 const CharType *String::c_str() const {
1001
1002 static const CharType zero = 0;
1003
1004 return size() ? &operator[](0) : &zero;
1005 }
1006
md5(const uint8_t * p_md5)1007 String String::md5(const uint8_t *p_md5) {
1008 return String::hex_encode_buffer(p_md5, 16);
1009 }
1010
hex_encode_buffer(const uint8_t * p_buffer,int p_len)1011 String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) {
1012 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1013
1014 String ret;
1015 char v[2] = { 0, 0 };
1016
1017 for (int i = 0; i < p_len; i++) {
1018 v[0] = hex[p_buffer[i] >> 4];
1019 ret += v;
1020 v[0] = hex[p_buffer[i] & 0xF];
1021 ret += v;
1022 }
1023
1024 return ret;
1025 }
1026
chr(CharType p_char)1027 String String::chr(CharType p_char) {
1028
1029 CharType c[2] = { p_char, 0 };
1030 return String(c);
1031 }
num(double p_num,int p_decimals)1032 String String::num(double p_num, int p_decimals) {
1033
1034 #ifndef NO_USE_STDLIB
1035
1036 if (p_decimals > 16)
1037 p_decimals = 16;
1038
1039 char fmt[7];
1040 fmt[0] = '%';
1041 fmt[1] = '.';
1042
1043 if (p_decimals < 0) {
1044
1045 fmt[1] = 'l';
1046 fmt[2] = 'f';
1047 fmt[3] = 0;
1048
1049 } else if (p_decimals < 10) {
1050 fmt[2] = '0' + p_decimals;
1051 fmt[3] = 'l';
1052 fmt[4] = 'f';
1053 fmt[5] = 0;
1054 } else {
1055 fmt[2] = '0' + (p_decimals / 10);
1056 fmt[3] = '0' + (p_decimals % 10);
1057 fmt[4] = 'l';
1058 fmt[5] = 'f';
1059 fmt[6] = 0;
1060 }
1061 char buf[256];
1062
1063 #if defined(__GNUC__) || defined(_MSC_VER)
1064 snprintf(buf, 256, fmt, p_num);
1065 #else
1066 sprintf(buf, fmt, p_num);
1067 #endif
1068
1069 buf[255] = 0;
1070 //destroy trailing zeroes
1071 {
1072
1073 bool period = false;
1074 int z = 0;
1075 while (buf[z]) {
1076 if (buf[z] == '.')
1077 period = true;
1078 z++;
1079 }
1080
1081 if (period) {
1082 z--;
1083 while (z > 0) {
1084
1085 if (buf[z] == '0') {
1086
1087 buf[z] = 0;
1088 } else if (buf[z] == '.') {
1089
1090 buf[z] = 0;
1091 break;
1092 } else {
1093
1094 break;
1095 }
1096
1097 z--;
1098 }
1099 }
1100 }
1101
1102 return buf;
1103 #else
1104
1105 String s;
1106 String sd;
1107 /* integer part */
1108
1109 bool neg = p_num < 0;
1110 p_num = ABS(p_num);
1111 int intn = (int)p_num;
1112
1113 /* decimal part */
1114
1115 if (p_decimals > 0 || (p_decimals == -1 && (int)p_num != p_num)) {
1116
1117 double dec = p_num - (float)((int)p_num);
1118
1119 int digit = 0;
1120 if (p_decimals > MAX_DIGITS)
1121 p_decimals = MAX_DIGITS;
1122
1123 int dec_int = 0;
1124 int dec_max = 0;
1125
1126 while (true) {
1127
1128 dec *= 10.0;
1129 dec_int = dec_int * 10 + (int)dec % 10;
1130 dec_max = dec_max * 10 + 9;
1131 digit++;
1132
1133 if (p_decimals == -1) {
1134
1135 if (digit == MAX_DIGITS) //no point in going to infinite
1136 break;
1137
1138 if ((dec - (float)((int)dec)) < 1e-6)
1139 break;
1140 }
1141
1142 if (digit == p_decimals)
1143 break;
1144 }
1145 dec *= 10;
1146 int last = (int)dec % 10;
1147
1148 if (last > 5) {
1149 if (dec_int == dec_max) {
1150
1151 dec_int = 0;
1152 intn++;
1153 } else {
1154
1155 dec_int++;
1156 }
1157 }
1158
1159 String decimal;
1160 for (int i = 0; i < digit; i++) {
1161
1162 char num[2] = { 0, 0 };
1163 num[0] = '0' + dec_int % 10;
1164 decimal = num + decimal;
1165 dec_int /= 10;
1166 }
1167 sd = '.' + decimal;
1168 }
1169
1170 if (intn == 0)
1171
1172 s = "0";
1173 else {
1174 while (intn) {
1175
1176 CharType num = '0' + (intn % 10);
1177 intn /= 10;
1178 s = num + s;
1179 }
1180 }
1181
1182 s = s + sd;
1183 if (neg)
1184 s = "-" + s;
1185 return s;
1186 #endif
1187 }
1188
num_int64(int64_t p_num,int base,bool capitalize_hex)1189 String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
1190
1191 bool sign = p_num < 0;
1192
1193 int64_t n = p_num;
1194
1195 int chars = 0;
1196 do {
1197 n /= base;
1198 chars++;
1199 } while (n);
1200
1201 if (sign)
1202 chars++;
1203 String s;
1204 s.resize(chars + 1);
1205 CharType *c = s.ptrw();
1206 c[chars] = 0;
1207 n = p_num;
1208 do {
1209 int mod = ABS(n % base);
1210 if (mod >= 10) {
1211 char a = (capitalize_hex ? 'A' : 'a');
1212 c[--chars] = a + (mod - 10);
1213 } else {
1214 c[--chars] = '0' + mod;
1215 }
1216
1217 n /= base;
1218 } while (n);
1219
1220 if (sign)
1221 c[0] = '-';
1222
1223 return s;
1224 }
1225
num_uint64(uint64_t p_num,int base,bool capitalize_hex)1226 String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
1227
1228 uint64_t n = p_num;
1229
1230 int chars = 0;
1231 do {
1232 n /= base;
1233 chars++;
1234 } while (n);
1235
1236 String s;
1237 s.resize(chars + 1);
1238 CharType *c = s.ptrw();
1239 c[chars] = 0;
1240 n = p_num;
1241 do {
1242 int mod = n % base;
1243 if (mod >= 10) {
1244 char a = (capitalize_hex ? 'A' : 'a');
1245 c[--chars] = a + (mod - 10);
1246 } else {
1247 c[--chars] = '0' + mod;
1248 }
1249
1250 n /= base;
1251 } while (n);
1252
1253 return s;
1254 }
1255
num_real(double p_num)1256 String String::num_real(double p_num) {
1257
1258 String s;
1259 String sd;
1260 /* integer part */
1261
1262 bool neg = p_num < 0;
1263 p_num = ABS(p_num);
1264 int intn = (int)p_num;
1265
1266 /* decimal part */
1267
1268 if ((int)p_num != p_num) {
1269
1270 double dec = p_num - (float)((int)p_num);
1271
1272 int digit = 0;
1273 int decimals = MAX_DIGITS;
1274
1275 int dec_int = 0;
1276 int dec_max = 0;
1277
1278 while (true) {
1279
1280 dec *= 10.0;
1281 dec_int = dec_int * 10 + (int)dec % 10;
1282 dec_max = dec_max * 10 + 9;
1283 digit++;
1284
1285 if ((dec - (float)((int)dec)) < 1e-6)
1286 break;
1287
1288 if (digit == decimals)
1289 break;
1290 }
1291
1292 dec *= 10;
1293 int last = (int)dec % 10;
1294
1295 if (last > 5) {
1296 if (dec_int == dec_max) {
1297
1298 dec_int = 0;
1299 intn++;
1300 } else {
1301
1302 dec_int++;
1303 }
1304 }
1305
1306 String decimal;
1307 for (int i = 0; i < digit; i++) {
1308
1309 char num[2] = { 0, 0 };
1310 num[0] = '0' + dec_int % 10;
1311 decimal = num + decimal;
1312 dec_int /= 10;
1313 }
1314 sd = '.' + decimal;
1315 } else {
1316 sd = ".0";
1317 }
1318
1319 if (intn == 0)
1320
1321 s = "0";
1322 else {
1323 while (intn) {
1324
1325 CharType num = '0' + (intn % 10);
1326 intn /= 10;
1327 s = num + s;
1328 }
1329 }
1330
1331 s = s + sd;
1332 if (neg)
1333 s = "-" + s;
1334 return s;
1335 }
1336
num_scientific(double p_num)1337 String String::num_scientific(double p_num) {
1338
1339 #ifndef NO_USE_STDLIB
1340
1341 char buf[256];
1342
1343 #if defined(__GNUC__) || defined(_MSC_VER)
1344
1345 #if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
1346 // MinGW and old MSC require _set_output_format() to conform to C99 output for printf
1347 unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
1348 #endif
1349 snprintf(buf, 256, "%lg", p_num);
1350
1351 #if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
1352 _set_output_format(old_exponent_format);
1353 #endif
1354
1355 #else
1356 sprintf(buf, "%.16lg", p_num);
1357 #endif
1358
1359 buf[255] = 0;
1360
1361 return buf;
1362 #else
1363
1364 return String::num(p_num);
1365 #endif
1366 }
1367
ascii(bool p_allow_extended) const1368 CharString String::ascii(bool p_allow_extended) const {
1369
1370 if (!length())
1371 return CharString();
1372
1373 CharString cs;
1374 cs.resize(size());
1375
1376 for (int i = 0; i < size(); i++)
1377 cs[i] = operator[](i);
1378
1379 return cs;
1380 }
1381
utf8(const char * p_utf8,int p_len)1382 String String::utf8(const char *p_utf8, int p_len) {
1383
1384 String ret;
1385 ret.parse_utf8(p_utf8, p_len);
1386
1387 return ret;
1388 };
1389
parse_utf8(const char * p_utf8,int p_len)1390 bool String::parse_utf8(const char *p_utf8, int p_len) {
1391
1392 #define _UNICERROR(m_err) print_line("Unicode error: " + String(m_err));
1393
1394 if (!p_utf8)
1395 return true;
1396
1397 String aux;
1398
1399 int cstr_size = 0;
1400 int str_size = 0;
1401
1402 /* HANDLE BOM (Byte Order Mark) */
1403 if (p_len < 0 || p_len >= 3) {
1404
1405 bool has_bom = uint8_t(p_utf8[0]) == 0xEF && uint8_t(p_utf8[1]) == 0xBB && uint8_t(p_utf8[2]) == 0xBF;
1406 if (has_bom) {
1407
1408 //just skip it
1409 if (p_len >= 0)
1410 p_len -= 3;
1411 p_utf8 += 3;
1412 }
1413 }
1414
1415 {
1416 const char *ptrtmp = p_utf8;
1417 const char *ptrtmp_limit = &p_utf8[p_len];
1418 int skip = 0;
1419 while (ptrtmp != ptrtmp_limit && *ptrtmp) {
1420
1421 if (skip == 0) {
1422
1423 uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp);
1424
1425 /* Determine the number of characters in sequence */
1426 if ((c & 0x80) == 0)
1427 skip = 0;
1428 else if ((c & 0xE0) == 0xC0)
1429 skip = 1;
1430 else if ((c & 0xF0) == 0xE0)
1431 skip = 2;
1432 else if ((c & 0xF8) == 0xF0)
1433 skip = 3;
1434 else if ((c & 0xFC) == 0xF8)
1435 skip = 4;
1436 else if ((c & 0xFE) == 0xFC)
1437 skip = 5;
1438 else {
1439 _UNICERROR("invalid skip");
1440 return true; //invalid utf8
1441 }
1442
1443 if (skip == 1 && (c & 0x1E) == 0) {
1444 //printf("overlong rejected\n");
1445 _UNICERROR("overlong rejected");
1446 return true; //reject overlong
1447 }
1448
1449 str_size++;
1450
1451 } else {
1452
1453 --skip;
1454 }
1455
1456 cstr_size++;
1457 ptrtmp++;
1458 }
1459
1460 if (skip) {
1461 _UNICERROR("no space left");
1462 return true; //not enough spac
1463 }
1464 }
1465
1466 if (str_size == 0) {
1467 clear();
1468 return false;
1469 }
1470
1471 resize(str_size + 1);
1472 CharType *dst = ptrw();
1473 dst[str_size] = 0;
1474
1475 while (cstr_size) {
1476
1477 int len = 0;
1478
1479 /* Determine the number of characters in sequence */
1480 if ((*p_utf8 & 0x80) == 0)
1481 len = 1;
1482 else if ((*p_utf8 & 0xE0) == 0xC0)
1483 len = 2;
1484 else if ((*p_utf8 & 0xF0) == 0xE0)
1485 len = 3;
1486 else if ((*p_utf8 & 0xF8) == 0xF0)
1487 len = 4;
1488 else if ((*p_utf8 & 0xFC) == 0xF8)
1489 len = 5;
1490 else if ((*p_utf8 & 0xFE) == 0xFC)
1491 len = 6;
1492 else {
1493 _UNICERROR("invalid len");
1494
1495 return true; //invalid UTF8
1496 }
1497
1498 if (len > cstr_size) {
1499 _UNICERROR("no space left");
1500 return true; //not enough space
1501 }
1502
1503 if (len == 2 && (*p_utf8 & 0x1E) == 0) {
1504 //printf("overlong rejected\n");
1505 _UNICERROR("no space left");
1506 return true; //reject overlong
1507 }
1508
1509 /* Convert the first character */
1510
1511 uint32_t unichar = 0;
1512
1513 if (len == 1)
1514 unichar = *p_utf8;
1515 else {
1516
1517 unichar = (0xFF >> (len + 1)) & *p_utf8;
1518
1519 for (int i = 1; i < len; i++) {
1520
1521 if ((p_utf8[i] & 0xC0) != 0x80) {
1522 _UNICERROR("invalid utf8");
1523 return true; //invalid utf8
1524 }
1525 if (unichar == 0 && i == 2 && ((p_utf8[i] & 0x7F) >> (7 - len)) == 0) {
1526 _UNICERROR("invalid utf8 overlong");
1527 return true; //no overlong
1528 }
1529 unichar = (unichar << 6) | (p_utf8[i] & 0x3F);
1530 }
1531 }
1532
1533 //printf("char %i, len %i\n",unichar,len);
1534 if (sizeof(wchar_t) == 2 && unichar > 0xFFFF) {
1535 unichar = ' '; //too long for windows
1536 }
1537
1538 *(dst++) = unichar;
1539 cstr_size -= len;
1540 p_utf8 += len;
1541 }
1542
1543 return false;
1544 }
1545
utf8() const1546 CharString String::utf8() const {
1547
1548 int l = length();
1549 if (!l)
1550 return CharString();
1551
1552 const CharType *d = &operator[](0);
1553 int fl = 0;
1554 for (int i = 0; i < l; i++) {
1555
1556 uint32_t c = d[i];
1557 if (c <= 0x7f) // 7 bits.
1558 fl += 1;
1559 else if (c <= 0x7ff) { // 11 bits
1560 fl += 2;
1561 } else if (c <= 0xffff) { // 16 bits
1562 fl += 3;
1563 } else if (c <= 0x001fffff) { // 21 bits
1564 fl += 4;
1565
1566 } else if (c <= 0x03ffffff) { // 26 bits
1567 fl += 5;
1568 } else if (c <= 0x7fffffff) { // 31 bits
1569 fl += 6;
1570 }
1571 }
1572
1573 CharString utf8s;
1574 if (fl == 0) {
1575 return utf8s;
1576 }
1577
1578 utf8s.resize(fl + 1);
1579 uint8_t *cdst = (uint8_t *)utf8s.get_data();
1580
1581 #define APPEND_CHAR(m_c) *(cdst++) = m_c
1582
1583 for (int i = 0; i < l; i++) {
1584
1585 uint32_t c = d[i];
1586
1587 if (c <= 0x7f) // 7 bits.
1588 APPEND_CHAR(c);
1589 else if (c <= 0x7ff) { // 11 bits
1590
1591 APPEND_CHAR(uint32_t(0xc0 | ((c >> 6) & 0x1f))); // Top 5 bits.
1592 APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
1593 } else if (c <= 0xffff) { // 16 bits
1594
1595 APPEND_CHAR(uint32_t(0xe0 | ((c >> 12) & 0x0f))); // Top 4 bits.
1596 APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Middle 6 bits.
1597 APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
1598 } else if (c <= 0x001fffff) { // 21 bits
1599
1600 APPEND_CHAR(uint32_t(0xf0 | ((c >> 18) & 0x07))); // Top 3 bits.
1601 APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper middle 6 bits.
1602 APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits.
1603 APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
1604 } else if (c <= 0x03ffffff) { // 26 bits
1605
1606 APPEND_CHAR(uint32_t(0xf8 | ((c >> 24) & 0x03))); // Top 2 bits.
1607 APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Upper middle 6 bits.
1608 APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // middle 6 bits.
1609 APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits.
1610 APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
1611 } else if (c <= 0x7fffffff) { // 31 bits
1612
1613 APPEND_CHAR(uint32_t(0xfc | ((c >> 30) & 0x01))); // Top 1 bit.
1614 APPEND_CHAR(uint32_t(0x80 | ((c >> 24) & 0x3f))); // Upper upper middle 6 bits.
1615 APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Lower upper middle 6 bits.
1616 APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper lower middle 6 bits.
1617 APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower lower middle 6 bits.
1618 APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
1619 }
1620 }
1621 #undef APPEND_CHAR
1622 *cdst = 0; //trailing zero
1623
1624 return utf8s;
1625 }
1626
1627 /*
1628 String::String(CharType p_char) {
1629
1630 shared=NULL;
1631 copy_from(p_char);
1632 }
1633 */
1634
String(const char * p_str)1635 String::String(const char *p_str) {
1636
1637 copy_from(p_str);
1638 }
1639
String(const CharType * p_str,int p_clip_to_len)1640 String::String(const CharType *p_str, int p_clip_to_len) {
1641
1642 copy_from(p_str, p_clip_to_len);
1643 }
1644
String(const StrRange & p_range)1645 String::String(const StrRange &p_range) {
1646
1647 if (!p_range.c_str)
1648 return;
1649
1650 copy_from(p_range.c_str, p_range.len);
1651 }
1652
hex_to_int(bool p_with_prefix) const1653 int String::hex_to_int(bool p_with_prefix) const {
1654
1655 if (p_with_prefix && length() < 3)
1656 return 0;
1657
1658 const CharType *s = ptr();
1659
1660 int sign = s[0] == '-' ? -1 : 1;
1661
1662 if (sign < 0) {
1663 s++;
1664 }
1665
1666 if (p_with_prefix) {
1667 if (s[0] != '0' || s[1] != 'x')
1668 return 0;
1669 s += 2;
1670 }
1671
1672 int hex = 0;
1673
1674 while (*s) {
1675
1676 CharType c = LOWERCASE(*s);
1677 int n;
1678 if (c >= '0' && c <= '9') {
1679 n = c - '0';
1680 } else if (c >= 'a' && c <= 'f') {
1681 n = (c - 'a') + 10;
1682 } else {
1683 return 0;
1684 }
1685 // Check for overflow/underflow, with special case to ensure INT32_MIN does not result in error
1686 bool overflow = ((hex > INT32_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT32_MAX >> 4) + 1))) || (sign == -1 && hex == (INT32_MAX >> 4) + 1 && c > '0');
1687 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1688 hex *= 16;
1689 hex += n;
1690 s++;
1691 }
1692
1693 return hex * sign;
1694 }
1695
hex_to_int64(bool p_with_prefix) const1696 int64_t String::hex_to_int64(bool p_with_prefix) const {
1697
1698 if (p_with_prefix && length() < 3)
1699 return 0;
1700
1701 const CharType *s = ptr();
1702
1703 int64_t sign = s[0] == '-' ? -1 : 1;
1704
1705 if (sign < 0) {
1706 s++;
1707 }
1708
1709 if (p_with_prefix) {
1710 if (s[0] != '0' || s[1] != 'x')
1711 return 0;
1712 s += 2;
1713 }
1714
1715 int64_t hex = 0;
1716
1717 while (*s) {
1718
1719 CharType c = LOWERCASE(*s);
1720 int64_t n;
1721 if (c >= '0' && c <= '9') {
1722 n = c - '0';
1723 } else if (c >= 'a' && c <= 'f') {
1724 n = (c - 'a') + 10;
1725 } else {
1726 return 0;
1727 }
1728 bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0');
1729 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1730 hex *= 16;
1731 hex += n;
1732 s++;
1733 }
1734
1735 return hex * sign;
1736 }
1737
bin_to_int64(bool p_with_prefix) const1738 int64_t String::bin_to_int64(bool p_with_prefix) const {
1739
1740 if (p_with_prefix && length() < 3)
1741 return 0;
1742
1743 const CharType *s = ptr();
1744
1745 int64_t sign = s[0] == '-' ? -1 : 1;
1746
1747 if (sign < 0) {
1748 s++;
1749 }
1750
1751 if (p_with_prefix) {
1752 if (s[0] != '0' || s[1] != 'b')
1753 return 0;
1754 s += 2;
1755 }
1756
1757 int64_t binary = 0;
1758
1759 while (*s) {
1760
1761 CharType c = LOWERCASE(*s);
1762 int64_t n;
1763 if (c == '0' || c == '1') {
1764 n = c - '0';
1765 } else {
1766 return 0;
1767 }
1768 // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
1769 bool overflow = ((binary > INT64_MAX / 2) && (sign == 1 || (sign == -1 && binary != (INT64_MAX >> 1) + 1))) || (sign == -1 && binary == (INT64_MAX >> 1) + 1 && c > '0');
1770 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1771 binary *= 2;
1772 binary += n;
1773 s++;
1774 }
1775
1776 return binary * sign;
1777 }
1778
to_int() const1779 int String::to_int() const {
1780
1781 if (length() == 0)
1782 return 0;
1783
1784 int to = (find(".") >= 0) ? find(".") : length();
1785
1786 int integer = 0;
1787 int sign = 1;
1788
1789 for (int i = 0; i < to; i++) {
1790
1791 CharType c = operator[](i);
1792 if (c >= '0' && c <= '9') {
1793 bool overflow = (integer > INT32_MAX / 10) || (integer == INT32_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
1794 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1795 integer *= 10;
1796 integer += c - '0';
1797
1798 } else if (integer == 0 && c == '-') {
1799
1800 sign = -sign;
1801 }
1802 }
1803
1804 return integer * sign;
1805 }
1806
to_int64() const1807 int64_t String::to_int64() const {
1808
1809 if (length() == 0)
1810 return 0;
1811
1812 int to = (find(".") >= 0) ? find(".") : length();
1813
1814 int64_t integer = 0;
1815 int64_t sign = 1;
1816
1817 for (int i = 0; i < to; i++) {
1818 CharType c = operator[](i);
1819 if (c >= '0' && c <= '9') {
1820 bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
1821 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1822 integer *= 10;
1823 integer += c - '0';
1824
1825 } else if (integer == 0 && c == '-') {
1826 sign = -sign;
1827 }
1828 }
1829
1830 return integer * sign;
1831 }
1832
to_int(const char * p_str,int p_len)1833 int String::to_int(const char *p_str, int p_len) {
1834
1835 int to = 0;
1836 if (p_len >= 0)
1837 to = p_len;
1838 else {
1839 while (p_str[to] != 0 && p_str[to] != '.')
1840 to++;
1841 }
1842
1843 int integer = 0;
1844 int sign = 1;
1845
1846 for (int i = 0; i < to; i++) {
1847
1848 char c = p_str[i];
1849 if (c >= '0' && c <= '9') {
1850 bool overflow = (integer > INT32_MAX / 10) || (integer == INT32_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
1851 ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
1852 integer *= 10;
1853 integer += c - '0';
1854
1855 } else if (c == '-' && integer == 0) {
1856
1857 sign = -sign;
1858 } else if (c != ' ')
1859 break;
1860 }
1861
1862 return integer * sign;
1863 }
1864
is_numeric() const1865 bool String::is_numeric() const {
1866
1867 if (length() == 0) {
1868 return false;
1869 };
1870
1871 int s = 0;
1872 if (operator[](0) == '-') ++s;
1873 bool dot = false;
1874 for (int i = s; i < length(); i++) {
1875
1876 CharType c = operator[](i);
1877 if (c == '.') {
1878 if (dot) {
1879 return false;
1880 };
1881 dot = true;
1882 }
1883 if (c < '0' || c > '9') {
1884 return false;
1885 };
1886 };
1887
1888 return true; // TODO: Use the parser below for this instead
1889 };
1890
1891 template <class C>
built_in_strtod(const C * string,C ** endPtr=NULL)1892 static double built_in_strtod(const C *string, /* A decimal ASCII floating-point number,
1893 * optionally preceded by white space. Must
1894 * have form "-I.FE-X", where I is the integer
1895 * part of the mantissa, F is the fractional
1896 * part of the mantissa, and X is the
1897 * exponent. Either of the signs may be "+",
1898 * "-", or omitted. Either I or F may be
1899 * omitted, or both. The decimal point isn't
1900 * necessary unless F is present. The "E" may
1901 * actually be an "e". E and X may both be
1902 * omitted (but not just one). */
1903 C **endPtr = NULL) /* If non-NULL, store terminating Cacter's
1904 * address here. */
1905 {
1906
1907 static const int maxExponent = 511; /* Largest possible base 10 exponent. Any
1908 * exponent larger than this will already
1909 * produce underflow or overflow, so there's
1910 * no need to worry about additional digits.
1911 */
1912 static const double powersOf10[] = { /* Table giving binary powers of 10. Entry */
1913 10., /* is 10^2^i. Used to convert decimal */
1914 100., /* exponents into floating-point numbers. */
1915 1.0e4,
1916 1.0e8,
1917 1.0e16,
1918 1.0e32,
1919 1.0e64,
1920 1.0e128,
1921 1.0e256
1922 };
1923
1924 bool sign, expSign = false;
1925 double fraction, dblExp;
1926 const double *d;
1927 const C *p;
1928 int c;
1929 int exp = 0; /* Exponent read from "EX" field. */
1930 int fracExp = 0; /* Exponent that derives from the fractional
1931 * part. Under normal circumstances, it is
1932 * the negative of the number of digits in F.
1933 * However, if I is very long, the last digits
1934 * of I get dropped (otherwise a long I with a
1935 * large negative exponent could cause an
1936 * unnecessary overflow on I alone). In this
1937 * case, fracExp is incremented one for each
1938 * dropped digit. */
1939 int mantSize; /* Number of digits in mantissa. */
1940 int decPt; /* Number of mantissa digits BEFORE decimal
1941 * point. */
1942 const C *pExp; /* Temporarily holds location of exponent in
1943 * string. */
1944
1945 /*
1946 * Strip off leading blanks and check for a sign.
1947 */
1948
1949 p = string;
1950 while (*p == ' ' || *p == '\t' || *p == '\n') {
1951 p += 1;
1952 }
1953 if (*p == '-') {
1954 sign = true;
1955 p += 1;
1956 } else {
1957 if (*p == '+') {
1958 p += 1;
1959 }
1960 sign = false;
1961 }
1962
1963 /*
1964 * Count the number of digits in the mantissa (including the decimal
1965 * point), and also locate the decimal point.
1966 */
1967
1968 decPt = -1;
1969 for (mantSize = 0;; mantSize += 1) {
1970 c = *p;
1971 if (!IS_DIGIT(c)) {
1972 if ((c != '.') || (decPt >= 0)) {
1973 break;
1974 }
1975 decPt = mantSize;
1976 }
1977 p += 1;
1978 }
1979
1980 /*
1981 * Now suck up the digits in the mantissa. Use two integers to collect 9
1982 * digits each (this is faster than using floating-point). If the mantissa
1983 * has more than 18 digits, ignore the extras, since they can't affect the
1984 * value anyway.
1985 */
1986
1987 pExp = p;
1988 p -= mantSize;
1989 if (decPt < 0) {
1990 decPt = mantSize;
1991 } else {
1992 mantSize -= 1; /* One of the digits was the point. */
1993 }
1994 if (mantSize > 18) {
1995 fracExp = decPt - 18;
1996 mantSize = 18;
1997 } else {
1998 fracExp = decPt - mantSize;
1999 }
2000 if (mantSize == 0) {
2001 fraction = 0.0;
2002 p = string;
2003 goto done;
2004 } else {
2005 int frac1, frac2;
2006
2007 frac1 = 0;
2008 for (; mantSize > 9; mantSize -= 1) {
2009 c = *p;
2010 p += 1;
2011 if (c == '.') {
2012 c = *p;
2013 p += 1;
2014 }
2015 frac1 = 10 * frac1 + (c - '0');
2016 }
2017 frac2 = 0;
2018 for (; mantSize > 0; mantSize -= 1) {
2019 c = *p;
2020 p += 1;
2021 if (c == '.') {
2022 c = *p;
2023 p += 1;
2024 }
2025 frac2 = 10 * frac2 + (c - '0');
2026 }
2027 fraction = (1.0e9 * frac1) + frac2;
2028 }
2029
2030 /*
2031 * Skim off the exponent.
2032 */
2033
2034 p = pExp;
2035 if ((*p == 'E') || (*p == 'e')) {
2036 p += 1;
2037 if (*p == '-') {
2038 expSign = true;
2039 p += 1;
2040 } else {
2041 if (*p == '+') {
2042 p += 1;
2043 }
2044 expSign = false;
2045 }
2046 if (!IS_DIGIT(CharType(*p))) {
2047 p = pExp;
2048 goto done;
2049 }
2050 while (IS_DIGIT(CharType(*p))) {
2051 exp = exp * 10 + (*p - '0');
2052 p += 1;
2053 }
2054 }
2055 if (expSign) {
2056 exp = fracExp - exp;
2057 } else {
2058 exp = fracExp + exp;
2059 }
2060
2061 /*
2062 * Generate a floating-point number that represents the exponent. Do this
2063 * by processing the exponent one bit at a time to combine many powers of
2064 * 2 of 10. Then combine the exponent with the fraction.
2065 */
2066
2067 if (exp < 0) {
2068 expSign = true;
2069 exp = -exp;
2070 } else {
2071 expSign = false;
2072 }
2073
2074 if (exp > maxExponent) {
2075 exp = maxExponent;
2076 WARN_PRINT("Exponent too high");
2077 }
2078 dblExp = 1.0;
2079 for (d = powersOf10; exp != 0; exp >>= 1, ++d) {
2080 if (exp & 01) {
2081 dblExp *= *d;
2082 }
2083 }
2084 if (expSign) {
2085 fraction /= dblExp;
2086 } else {
2087 fraction *= dblExp;
2088 }
2089
2090 done:
2091 if (endPtr != NULL) {
2092 *endPtr = (C *)p;
2093 }
2094
2095 if (sign) {
2096 return -fraction;
2097 }
2098 return fraction;
2099 }
2100
2101 #define READING_SIGN 0
2102 #define READING_INT 1
2103 #define READING_DEC 2
2104 #define READING_EXP 3
2105 #define READING_DONE 4
2106
to_double(const char * p_str)2107 double String::to_double(const char *p_str) {
2108
2109 #ifndef NO_USE_STDLIB
2110 return built_in_strtod<char>(p_str);
2111 //return atof(p_str); DOES NOT WORK ON ANDROID(??)
2112 #else
2113 return built_in_strtod<char>(p_str);
2114 #endif
2115 }
2116
to_float() const2117 float String::to_float() const {
2118
2119 return to_double();
2120 }
2121
to_double(const CharType * p_str,const CharType ** r_end)2122 double String::to_double(const CharType *p_str, const CharType **r_end) {
2123
2124 return built_in_strtod<CharType>(p_str, (CharType **)r_end);
2125 }
2126
to_int(const CharType * p_str,int p_len)2127 int64_t String::to_int(const CharType *p_str, int p_len) {
2128
2129 if (p_len == 0 || !p_str[0])
2130 return 0;
2131 ///@todo make more exact so saving and loading does not lose precision
2132
2133 int64_t integer = 0;
2134 int64_t sign = 1;
2135 int reading = READING_SIGN;
2136
2137 const CharType *str = p_str;
2138 const CharType *limit = &p_str[p_len];
2139
2140 while (*str && reading != READING_DONE && str != limit) {
2141
2142 CharType c = *(str++);
2143 switch (reading) {
2144 case READING_SIGN: {
2145 if (c >= '0' && c <= '9') {
2146 reading = READING_INT;
2147 // let it fallthrough
2148 } else if (c == '-') {
2149 sign = -1;
2150 reading = READING_INT;
2151 break;
2152 } else if (c == '+') {
2153 sign = 1;
2154 reading = READING_INT;
2155 break;
2156 } else {
2157 break;
2158 }
2159 }
2160 case READING_INT: {
2161
2162 if (c >= '0' && c <= '9') {
2163
2164 if (integer > INT64_MAX / 10) {
2165 String number("");
2166 str = p_str;
2167 while (*str && str != limit) {
2168 number += *(str++);
2169 }
2170 ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
2171 }
2172 integer *= 10;
2173 integer += c - '0';
2174 } else {
2175 reading = READING_DONE;
2176 }
2177
2178 } break;
2179 }
2180 }
2181
2182 return sign * integer;
2183 }
2184
to_double() const2185 double String::to_double() const {
2186
2187 if (empty())
2188 return 0;
2189 #ifndef NO_USE_STDLIB
2190 return built_in_strtod<CharType>(c_str());
2191 //return wcstod(c_str(),NULL); DOES NOT WORK ON ANDROID :(
2192 #else
2193 return built_in_strtod<CharType>(c_str());
2194 #endif
2195 }
2196
operator ==(const char * p_chr,const String & p_str)2197 bool operator==(const char *p_chr, const String &p_str) {
2198
2199 return p_str == p_chr;
2200 }
2201
operator +(const char * p_chr,const String & p_str)2202 String operator+(const char *p_chr, const String &p_str) {
2203
2204 String tmp = p_chr;
2205 tmp += p_str;
2206 return tmp;
2207 }
operator +(CharType p_chr,const String & p_str)2208 String operator+(CharType p_chr, const String &p_str) {
2209
2210 return (String::chr(p_chr) + p_str);
2211 }
2212
hash(const char * p_cstr)2213 uint32_t String::hash(const char *p_cstr) {
2214
2215 uint32_t hashv = 5381;
2216 uint32_t c;
2217
2218 while ((c = *p_cstr++))
2219 hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
2220
2221 return hashv;
2222 }
2223
hash(const char * p_cstr,int p_len)2224 uint32_t String::hash(const char *p_cstr, int p_len) {
2225
2226 uint32_t hashv = 5381;
2227 for (int i = 0; i < p_len; i++)
2228 hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */
2229
2230 return hashv;
2231 }
2232
hash(const CharType * p_cstr,int p_len)2233 uint32_t String::hash(const CharType *p_cstr, int p_len) {
2234
2235 uint32_t hashv = 5381;
2236 for (int i = 0; i < p_len; i++)
2237 hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */
2238
2239 return hashv;
2240 }
2241
hash(const CharType * p_cstr)2242 uint32_t String::hash(const CharType *p_cstr) {
2243
2244 uint32_t hashv = 5381;
2245 uint32_t c;
2246
2247 while ((c = *p_cstr++))
2248 hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
2249
2250 return hashv;
2251 }
2252
hash() const2253 uint32_t String::hash() const {
2254
2255 /* simple djb2 hashing */
2256
2257 const CharType *chr = c_str();
2258 uint32_t hashv = 5381;
2259 uint32_t c;
2260
2261 while ((c = *chr++))
2262 hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
2263
2264 return hashv;
2265 }
2266
hash64() const2267 uint64_t String::hash64() const {
2268
2269 /* simple djb2 hashing */
2270
2271 const CharType *chr = c_str();
2272 uint64_t hashv = 5381;
2273 uint64_t c;
2274
2275 while ((c = *chr++))
2276 hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */
2277
2278 return hashv;
2279 }
2280
md5_text() const2281 String String::md5_text() const {
2282
2283 CharString cs = utf8();
2284 unsigned char hash[16];
2285 CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash);
2286 return String::hex_encode_buffer(hash, 16);
2287 }
2288
sha1_text() const2289 String String::sha1_text() const {
2290 CharString cs = utf8();
2291 unsigned char hash[20];
2292 CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash);
2293 return String::hex_encode_buffer(hash, 20);
2294 }
2295
sha256_text() const2296 String String::sha256_text() const {
2297 CharString cs = utf8();
2298 unsigned char hash[32];
2299 CryptoCore::sha256((unsigned char *)cs.ptr(), cs.length(), hash);
2300 return String::hex_encode_buffer(hash, 32);
2301 }
2302
md5_buffer() const2303 Vector<uint8_t> String::md5_buffer() const {
2304
2305 CharString cs = utf8();
2306 unsigned char hash[16];
2307 CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash);
2308
2309 Vector<uint8_t> ret;
2310 ret.resize(16);
2311 for (int i = 0; i < 16; i++) {
2312 ret.write[i] = hash[i];
2313 }
2314 return ret;
2315 };
2316
sha1_buffer() const2317 Vector<uint8_t> String::sha1_buffer() const {
2318 CharString cs = utf8();
2319 unsigned char hash[20];
2320 CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash);
2321
2322 Vector<uint8_t> ret;
2323 ret.resize(20);
2324 for (int i = 0; i < 20; i++) {
2325 ret.write[i] = hash[i];
2326 }
2327
2328 return ret;
2329 }
2330
sha256_buffer() const2331 Vector<uint8_t> String::sha256_buffer() const {
2332 CharString cs = utf8();
2333 unsigned char hash[32];
2334 CryptoCore::sha256((unsigned char *)cs.ptr(), cs.length(), hash);
2335
2336 Vector<uint8_t> ret;
2337 ret.resize(32);
2338 for (int i = 0; i < 32; i++) {
2339 ret.write[i] = hash[i];
2340 }
2341 return ret;
2342 }
2343
insert(int p_at_pos,const String & p_string) const2344 String String::insert(int p_at_pos, const String &p_string) const {
2345
2346 if (p_at_pos < 0)
2347 return *this;
2348
2349 if (p_at_pos > length())
2350 p_at_pos = length();
2351
2352 String pre;
2353 if (p_at_pos > 0)
2354 pre = substr(0, p_at_pos);
2355
2356 String post;
2357 if (p_at_pos < length())
2358 post = substr(p_at_pos, length() - p_at_pos);
2359
2360 return pre + p_string + post;
2361 }
substr(int p_from,int p_chars) const2362 String String::substr(int p_from, int p_chars) const {
2363
2364 if (p_chars == -1)
2365 p_chars = length() - p_from;
2366
2367 if (empty() || p_from < 0 || p_from >= length() || p_chars <= 0)
2368 return "";
2369
2370 if ((p_from + p_chars) > length()) {
2371
2372 p_chars = length() - p_from;
2373 }
2374
2375 if (p_from == 0 && p_chars >= length()) {
2376
2377 return String(*this);
2378 }
2379
2380 String s = String();
2381 s.copy_from_unchecked(&c_str()[p_from], p_chars);
2382 return s;
2383 }
2384
find_last(const String & p_str) const2385 int String::find_last(const String &p_str) const {
2386
2387 int pos = -1;
2388 int findfrom = 0;
2389 int findres = -1;
2390 while ((findres = find(p_str, findfrom)) != -1) {
2391
2392 pos = findres;
2393 findfrom = pos + 1;
2394 }
2395
2396 return pos;
2397 }
2398
find(const String & p_str,int p_from) const2399 int String::find(const String &p_str, int p_from) const {
2400
2401 if (p_from < 0)
2402 return -1;
2403
2404 const int src_len = p_str.length();
2405
2406 const int len = length();
2407
2408 if (src_len == 0 || len == 0)
2409 return -1; // won't find anything!
2410
2411 const CharType *src = c_str();
2412 const CharType *str = p_str.c_str();
2413
2414 for (int i = p_from; i <= (len - src_len); i++) {
2415
2416 bool found = true;
2417 for (int j = 0; j < src_len; j++) {
2418
2419 int read_pos = i + j;
2420
2421 if (read_pos >= len) {
2422
2423 ERR_PRINT("read_pos>=len");
2424 return -1;
2425 };
2426
2427 if (src[read_pos] != str[j]) {
2428 found = false;
2429 break;
2430 }
2431 }
2432
2433 if (found)
2434 return i;
2435 }
2436
2437 return -1;
2438 }
2439
find(const char * p_str,int p_from) const2440 int String::find(const char *p_str, int p_from) const {
2441
2442 if (p_from < 0)
2443 return -1;
2444
2445 const int len = length();
2446
2447 if (len == 0)
2448 return -1; // won't find anything!
2449
2450 const CharType *src = c_str();
2451
2452 int src_len = 0;
2453 while (p_str[src_len] != '\0')
2454 src_len++;
2455
2456 if (src_len == 1) {
2457
2458 const char needle = p_str[0];
2459
2460 for (int i = p_from; i < len; i++) {
2461
2462 if (src[i] == needle) {
2463 return i;
2464 }
2465 }
2466
2467 } else {
2468
2469 for (int i = p_from; i <= (len - src_len); i++) {
2470
2471 bool found = true;
2472 for (int j = 0; j < src_len; j++) {
2473
2474 int read_pos = i + j;
2475
2476 if (read_pos >= len) {
2477
2478 ERR_PRINT("read_pos>=len");
2479 return -1;
2480 };
2481
2482 if (src[read_pos] != p_str[j]) {
2483 found = false;
2484 break;
2485 }
2486 }
2487
2488 if (found)
2489 return i;
2490 }
2491 }
2492
2493 return -1;
2494 }
2495
find_char(const CharType & p_char,int p_from) const2496 int String::find_char(const CharType &p_char, int p_from) const {
2497 return _cowdata.find(p_char, p_from);
2498 }
2499
findmk(const Vector<String> & p_keys,int p_from,int * r_key) const2500 int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const {
2501
2502 if (p_from < 0)
2503 return -1;
2504 if (p_keys.size() == 0)
2505 return -1;
2506
2507 //int src_len=p_str.length();
2508 const String *keys = &p_keys[0];
2509 int key_count = p_keys.size();
2510 int len = length();
2511
2512 if (len == 0)
2513 return -1; // won't find anything!
2514
2515 const CharType *src = c_str();
2516
2517 for (int i = p_from; i < len; i++) {
2518
2519 bool found = true;
2520 for (int k = 0; k < key_count; k++) {
2521
2522 found = true;
2523 if (r_key)
2524 *r_key = k;
2525 const CharType *cmp = keys[k].c_str();
2526 int l = keys[k].length();
2527
2528 for (int j = 0; j < l; j++) {
2529
2530 int read_pos = i + j;
2531
2532 if (read_pos >= len) {
2533
2534 found = false;
2535 break;
2536 };
2537
2538 if (src[read_pos] != cmp[j]) {
2539 found = false;
2540 break;
2541 }
2542 }
2543 if (found)
2544 break;
2545 }
2546
2547 if (found)
2548 return i;
2549 }
2550
2551 return -1;
2552 }
2553
findn(const String & p_str,int p_from) const2554 int String::findn(const String &p_str, int p_from) const {
2555
2556 if (p_from < 0)
2557 return -1;
2558
2559 int src_len = p_str.length();
2560
2561 if (src_len == 0 || length() == 0)
2562 return -1; // won't find anything!
2563
2564 const CharType *srcd = c_str();
2565
2566 for (int i = p_from; i <= (length() - src_len); i++) {
2567
2568 bool found = true;
2569 for (int j = 0; j < src_len; j++) {
2570
2571 int read_pos = i + j;
2572
2573 if (read_pos >= length()) {
2574
2575 ERR_PRINT("read_pos>=length()");
2576 return -1;
2577 };
2578
2579 CharType src = _find_lower(srcd[read_pos]);
2580 CharType dst = _find_lower(p_str[j]);
2581
2582 if (src != dst) {
2583 found = false;
2584 break;
2585 }
2586 }
2587
2588 if (found)
2589 return i;
2590 }
2591
2592 return -1;
2593 }
2594
rfind(const String & p_str,int p_from) const2595 int String::rfind(const String &p_str, int p_from) const {
2596
2597 // establish a limit
2598 int limit = length() - p_str.length();
2599 if (limit < 0)
2600 return -1;
2601
2602 // establish a starting point
2603 if (p_from < 0)
2604 p_from = limit;
2605 else if (p_from > limit)
2606 p_from = limit;
2607
2608 int src_len = p_str.length();
2609 int len = length();
2610
2611 if (src_len == 0 || len == 0)
2612 return -1; // won't find anything!
2613
2614 const CharType *src = c_str();
2615
2616 for (int i = p_from; i >= 0; i--) {
2617
2618 bool found = true;
2619 for (int j = 0; j < src_len; j++) {
2620
2621 int read_pos = i + j;
2622
2623 if (read_pos >= len) {
2624
2625 ERR_PRINT("read_pos>=len");
2626 return -1;
2627 };
2628
2629 if (src[read_pos] != p_str[j]) {
2630 found = false;
2631 break;
2632 }
2633 }
2634
2635 if (found)
2636 return i;
2637 }
2638
2639 return -1;
2640 }
rfindn(const String & p_str,int p_from) const2641 int String::rfindn(const String &p_str, int p_from) const {
2642
2643 // establish a limit
2644 int limit = length() - p_str.length();
2645 if (limit < 0)
2646 return -1;
2647
2648 // establish a starting point
2649 if (p_from < 0)
2650 p_from = limit;
2651 else if (p_from > limit)
2652 p_from = limit;
2653
2654 int src_len = p_str.length();
2655 int len = length();
2656
2657 if (src_len == 0 || len == 0)
2658 return -1; // won't find anything!
2659
2660 const CharType *src = c_str();
2661
2662 for (int i = p_from; i >= 0; i--) {
2663
2664 bool found = true;
2665 for (int j = 0; j < src_len; j++) {
2666
2667 int read_pos = i + j;
2668
2669 if (read_pos >= len) {
2670
2671 ERR_PRINT("read_pos>=len");
2672 return -1;
2673 };
2674
2675 CharType srcc = _find_lower(src[read_pos]);
2676 CharType dstc = _find_lower(p_str[j]);
2677
2678 if (srcc != dstc) {
2679 found = false;
2680 break;
2681 }
2682 }
2683
2684 if (found)
2685 return i;
2686 }
2687
2688 return -1;
2689 }
2690
ends_with(const String & p_string) const2691 bool String::ends_with(const String &p_string) const {
2692
2693 int pos = find_last(p_string);
2694 if (pos == -1)
2695 return false;
2696 return pos + p_string.length() == length();
2697 }
2698
begins_with(const String & p_string) const2699 bool String::begins_with(const String &p_string) const {
2700
2701 if (p_string.length() > length())
2702 return false;
2703
2704 int l = p_string.length();
2705 if (l == 0)
2706 return true;
2707
2708 const CharType *src = &p_string[0];
2709 const CharType *str = &operator[](0);
2710
2711 int i = 0;
2712 for (; i < l; i++) {
2713
2714 if (src[i] != str[i])
2715 return false;
2716 }
2717
2718 // only if i == l the p_string matches the beginning
2719 return i == l;
2720 }
begins_with(const char * p_string) const2721 bool String::begins_with(const char *p_string) const {
2722
2723 int l = length();
2724 if (l == 0 || !p_string)
2725 return false;
2726
2727 const CharType *str = &operator[](0);
2728 int i = 0;
2729
2730 while (*p_string && i < l) {
2731
2732 if (*p_string != str[i])
2733 return false;
2734 i++;
2735 p_string++;
2736 }
2737
2738 return *p_string == 0;
2739 }
2740
is_enclosed_in(const String & p_string) const2741 bool String::is_enclosed_in(const String &p_string) const {
2742
2743 return begins_with(p_string) && ends_with(p_string);
2744 }
2745
is_subsequence_of(const String & p_string) const2746 bool String::is_subsequence_of(const String &p_string) const {
2747
2748 return _base_is_subsequence_of(p_string, false);
2749 }
2750
is_subsequence_ofi(const String & p_string) const2751 bool String::is_subsequence_ofi(const String &p_string) const {
2752
2753 return _base_is_subsequence_of(p_string, true);
2754 }
2755
is_quoted() const2756 bool String::is_quoted() const {
2757
2758 return is_enclosed_in("\"") || is_enclosed_in("'");
2759 }
2760
_count(const String & p_string,int p_from,int p_to,bool p_case_insensitive) const2761 int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const {
2762 if (p_string.empty()) {
2763 return 0;
2764 }
2765 int len = length();
2766 int slen = p_string.length();
2767 if (len < slen) {
2768 return 0;
2769 }
2770 String str;
2771 if (p_from >= 0 && p_to >= 0) {
2772 if (p_to == 0) {
2773 p_to = len;
2774 } else if (p_from >= p_to) {
2775 return 0;
2776 }
2777 if (p_from == 0 && p_to == len) {
2778 str = String();
2779 str.copy_from_unchecked(&c_str()[0], len);
2780 } else {
2781 str = substr(p_from, p_to - p_from);
2782 }
2783 } else {
2784 return 0;
2785 }
2786 int c = 0;
2787 int idx = -1;
2788 do {
2789 idx = p_case_insensitive ? str.findn(p_string) : str.find(p_string);
2790 if (idx != -1) {
2791 str = str.substr(idx + slen, str.length() - slen);
2792 ++c;
2793 }
2794 } while (idx != -1);
2795 return c;
2796 }
2797
count(const String & p_string,int p_from,int p_to) const2798 int String::count(const String &p_string, int p_from, int p_to) const {
2799 return _count(p_string, p_from, p_to, false);
2800 }
2801
countn(const String & p_string,int p_from,int p_to) const2802 int String::countn(const String &p_string, int p_from, int p_to) const {
2803 return _count(p_string, p_from, p_to, true);
2804 }
2805
_base_is_subsequence_of(const String & p_string,bool case_insensitive) const2806 bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
2807
2808 int len = length();
2809 if (len == 0) {
2810 // Technically an empty string is subsequence of any string
2811 return true;
2812 }
2813
2814 if (len > p_string.length()) {
2815 return false;
2816 }
2817
2818 const CharType *src = &operator[](0);
2819 const CharType *tgt = &p_string[0];
2820
2821 for (; *src && *tgt; tgt++) {
2822 bool match = false;
2823 if (case_insensitive) {
2824 CharType srcc = _find_lower(*src);
2825 CharType tgtc = _find_lower(*tgt);
2826 match = srcc == tgtc;
2827 } else {
2828 match = *src == *tgt;
2829 }
2830 if (match) {
2831 src++;
2832 if (!*src) {
2833 return true;
2834 }
2835 }
2836 }
2837
2838 return false;
2839 }
2840
bigrams() const2841 Vector<String> String::bigrams() const {
2842 int n_pairs = length() - 1;
2843 Vector<String> b;
2844 if (n_pairs <= 0) {
2845 return b;
2846 }
2847 b.resize(n_pairs);
2848 for (int i = 0; i < n_pairs; i++) {
2849 b.write[i] = substr(i, 2);
2850 }
2851 return b;
2852 }
2853
2854 // Similarity according to Sorensen-Dice coefficient
similarity(const String & p_string) const2855 float String::similarity(const String &p_string) const {
2856 if (operator==(p_string)) {
2857 // Equal strings are totally similar
2858 return 1.0f;
2859 }
2860 if (length() < 2 || p_string.length() < 2) {
2861 // No way to calculate similarity without a single bigram
2862 return 0.0f;
2863 }
2864
2865 Vector<String> src_bigrams = bigrams();
2866 Vector<String> tgt_bigrams = p_string.bigrams();
2867
2868 int src_size = src_bigrams.size();
2869 int tgt_size = tgt_bigrams.size();
2870
2871 float sum = src_size + tgt_size;
2872 float inter = 0;
2873 for (int i = 0; i < src_size; i++) {
2874 for (int j = 0; j < tgt_size; j++) {
2875 if (src_bigrams[i] == tgt_bigrams[j]) {
2876 inter++;
2877 break;
2878 }
2879 }
2880 }
2881
2882 return (2.0f * inter) / sum;
2883 }
2884
_wildcard_match(const CharType * p_pattern,const CharType * p_string,bool p_case_sensitive)2885 static bool _wildcard_match(const CharType *p_pattern, const CharType *p_string, bool p_case_sensitive) {
2886 switch (*p_pattern) {
2887 case '\0':
2888 return !*p_string;
2889 case '*':
2890 return _wildcard_match(p_pattern + 1, p_string, p_case_sensitive) || (*p_string && _wildcard_match(p_pattern, p_string + 1, p_case_sensitive));
2891 case '?':
2892 return *p_string && (*p_string != '.') && _wildcard_match(p_pattern + 1, p_string + 1, p_case_sensitive);
2893 default:
2894
2895 return (p_case_sensitive ? (*p_string == *p_pattern) : (_find_upper(*p_string) == _find_upper(*p_pattern))) && _wildcard_match(p_pattern + 1, p_string + 1, p_case_sensitive);
2896 }
2897 }
2898
match(const String & p_wildcard) const2899 bool String::match(const String &p_wildcard) const {
2900
2901 if (!p_wildcard.length() || !length())
2902 return false;
2903
2904 return _wildcard_match(p_wildcard.c_str(), c_str(), true);
2905 }
2906
matchn(const String & p_wildcard) const2907 bool String::matchn(const String &p_wildcard) const {
2908
2909 if (!p_wildcard.length() || !length())
2910 return false;
2911 return _wildcard_match(p_wildcard.c_str(), c_str(), false);
2912 }
2913
format(const Variant & values,String placeholder) const2914 String String::format(const Variant &values, String placeholder) const {
2915
2916 String new_string = String(this->ptr());
2917
2918 if (values.get_type() == Variant::ARRAY) {
2919 Array values_arr = values;
2920
2921 for (int i = 0; i < values_arr.size(); i++) {
2922 String i_as_str = String::num_int64(i);
2923
2924 if (values_arr[i].get_type() == Variant::ARRAY) { //Array in Array structure [["name","RobotGuy"],[0,"godot"],["strength",9000.91]]
2925 Array value_arr = values_arr[i];
2926
2927 if (value_arr.size() == 2) {
2928 Variant v_key = value_arr[0];
2929 String key = v_key;
2930 if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
2931 key = key.substr(1, key.length() - 2);
2932 }
2933
2934 Variant v_val = value_arr[1];
2935 String val = v_val;
2936
2937 if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
2938 val = val.substr(1, val.length() - 2);
2939 }
2940
2941 new_string = new_string.replace(placeholder.replace("_", key), val);
2942 } else {
2943 ERR_PRINT(String("STRING.format Inner Array size != 2 ").ascii().get_data());
2944 }
2945 } else { //Array structure ["RobotGuy","Logis","rookie"]
2946 Variant v_val = values_arr[i];
2947 String val = v_val;
2948
2949 if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
2950 val = val.substr(1, val.length() - 2);
2951 }
2952
2953 if (placeholder.find("_") > -1) {
2954 new_string = new_string.replace(placeholder.replace("_", i_as_str), val);
2955 } else {
2956 new_string = new_string.replace_first(placeholder, val);
2957 }
2958 }
2959 }
2960 } else if (values.get_type() == Variant::DICTIONARY) {
2961 Dictionary d = values;
2962 List<Variant> keys;
2963 d.get_key_list(&keys);
2964
2965 for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
2966 String key = E->get();
2967 String val = d[E->get()];
2968
2969 if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
2970 key = key.substr(1, key.length() - 2);
2971 }
2972
2973 if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
2974 val = val.substr(1, val.length() - 2);
2975 }
2976
2977 new_string = new_string.replace(placeholder.replace("_", key), val);
2978 }
2979 } else {
2980 ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data());
2981 }
2982
2983 return new_string;
2984 }
2985
replace(const String & p_key,const String & p_with) const2986 String String::replace(const String &p_key, const String &p_with) const {
2987
2988 String new_string;
2989 int search_from = 0;
2990 int result = 0;
2991
2992 while ((result = find(p_key, search_from)) >= 0) {
2993
2994 new_string += substr(search_from, result - search_from);
2995 new_string += p_with;
2996 search_from = result + p_key.length();
2997 }
2998
2999 if (search_from == 0) {
3000
3001 return *this;
3002 }
3003
3004 new_string += substr(search_from, length() - search_from);
3005
3006 return new_string;
3007 }
3008
replace(const char * p_key,const char * p_with) const3009 String String::replace(const char *p_key, const char *p_with) const {
3010
3011 String new_string;
3012 int search_from = 0;
3013 int result = 0;
3014
3015 while ((result = find(p_key, search_from)) >= 0) {
3016
3017 new_string += substr(search_from, result - search_from);
3018 new_string += p_with;
3019 int k = 0;
3020 while (p_key[k] != '\0')
3021 k++;
3022 search_from = result + k;
3023 }
3024
3025 if (search_from == 0) {
3026
3027 return *this;
3028 }
3029
3030 new_string += substr(search_from, length() - search_from);
3031
3032 return new_string;
3033 }
3034
replace_first(const String & p_key,const String & p_with) const3035 String String::replace_first(const String &p_key, const String &p_with) const {
3036
3037 int pos = find(p_key);
3038 if (pos >= 0) {
3039 return substr(0, pos) + p_with + substr(pos + p_key.length(), length());
3040 }
3041
3042 return *this;
3043 }
replacen(const String & p_key,const String & p_with) const3044 String String::replacen(const String &p_key, const String &p_with) const {
3045
3046 String new_string;
3047 int search_from = 0;
3048 int result = 0;
3049
3050 while ((result = findn(p_key, search_from)) >= 0) {
3051
3052 new_string += substr(search_from, result - search_from);
3053 new_string += p_with;
3054 search_from = result + p_key.length();
3055 }
3056
3057 if (search_from == 0) {
3058
3059 return *this;
3060 }
3061
3062 new_string += substr(search_from, length() - search_from);
3063 return new_string;
3064 }
3065
repeat(int p_count) const3066 String String::repeat(int p_count) const {
3067
3068 ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number.");
3069
3070 String new_string;
3071 const CharType *src = this->c_str();
3072
3073 new_string.resize(length() * p_count + 1);
3074 new_string[length() * p_count] = 0;
3075
3076 for (int i = 0; i < p_count; i++)
3077 for (int j = 0; j < length(); j++)
3078 new_string[i * length() + j] = src[j];
3079
3080 return new_string;
3081 }
3082
left(int p_pos) const3083 String String::left(int p_pos) const {
3084
3085 if (p_pos <= 0)
3086 return "";
3087
3088 if (p_pos >= length())
3089 return *this;
3090
3091 return substr(0, p_pos);
3092 }
3093
right(int p_pos) const3094 String String::right(int p_pos) const {
3095
3096 if (p_pos >= length())
3097 return "";
3098
3099 if (p_pos <= 0)
3100 return *this;
3101
3102 return substr(p_pos, (length() - p_pos));
3103 }
3104
ord_at(int p_idx) const3105 CharType String::ord_at(int p_idx) const {
3106
3107 ERR_FAIL_INDEX_V(p_idx, length(), 0);
3108 return operator[](p_idx);
3109 }
3110
dedent() const3111 String String::dedent() const {
3112
3113 String new_string;
3114 String indent;
3115 bool has_indent = false;
3116 bool has_text = false;
3117 int line_start = 0;
3118 int indent_stop = -1;
3119
3120 for (int i = 0; i < length(); i++) {
3121
3122 CharType c = operator[](i);
3123 if (c == '\n') {
3124 if (has_text)
3125 new_string += substr(indent_stop, i - indent_stop);
3126 new_string += "\n";
3127 has_text = false;
3128 line_start = i + 1;
3129 indent_stop = -1;
3130 } else if (!has_text) {
3131 if (c > 32) {
3132 has_text = true;
3133 if (!has_indent) {
3134 has_indent = true;
3135 indent = substr(line_start, i - line_start);
3136 indent_stop = i;
3137 }
3138 }
3139 if (has_indent && indent_stop < 0) {
3140 int j = i - line_start;
3141 if (j >= indent.length() || c != indent[j])
3142 indent_stop = i;
3143 }
3144 }
3145 }
3146
3147 if (has_text)
3148 new_string += substr(indent_stop, length() - indent_stop);
3149
3150 return new_string;
3151 }
3152
strip_edges(bool left,bool right) const3153 String String::strip_edges(bool left, bool right) const {
3154
3155 int len = length();
3156 int beg = 0, end = len;
3157
3158 if (left) {
3159 for (int i = 0; i < len; i++) {
3160
3161 if (operator[](i) <= 32)
3162 beg++;
3163 else
3164 break;
3165 }
3166 }
3167
3168 if (right) {
3169 for (int i = (int)(len - 1); i >= 0; i--) {
3170
3171 if (operator[](i) <= 32)
3172 end--;
3173 else
3174 break;
3175 }
3176 }
3177
3178 if (beg == 0 && end == len)
3179 return *this;
3180
3181 return substr(beg, end - beg);
3182 }
3183
strip_escapes() const3184 String String::strip_escapes() const {
3185
3186 String new_string;
3187 for (int i = 0; i < length(); i++) {
3188
3189 // Escape characters on first page of the ASCII table, before 32 (Space).
3190 if (operator[](i) < 32)
3191 continue;
3192 new_string += operator[](i);
3193 }
3194
3195 return new_string;
3196 }
3197
lstrip(const String & p_chars) const3198 String String::lstrip(const String &p_chars) const {
3199
3200 int len = length();
3201 int beg;
3202
3203 for (beg = 0; beg < len; beg++) {
3204
3205 if (p_chars.find_char(get(beg)) == -1)
3206 break;
3207 }
3208
3209 if (beg == 0)
3210 return *this;
3211
3212 return substr(beg, len - beg);
3213 }
3214
rstrip(const String & p_chars) const3215 String String::rstrip(const String &p_chars) const {
3216
3217 int len = length();
3218 int end;
3219
3220 for (end = len - 1; end >= 0; end--) {
3221
3222 if (p_chars.find_char(get(end)) == -1)
3223 break;
3224 }
3225
3226 if (end == len - 1)
3227 return *this;
3228
3229 return substr(0, end + 1);
3230 }
3231
simplify_path() const3232 String String::simplify_path() const {
3233
3234 String s = *this;
3235 String drive;
3236 if (s.begins_with("local://")) {
3237 drive = "local://";
3238 s = s.substr(8, s.length());
3239 } else if (s.begins_with("res://")) {
3240
3241 drive = "res://";
3242 s = s.substr(6, s.length());
3243 } else if (s.begins_with("user://")) {
3244
3245 drive = "user://";
3246 s = s.substr(7, s.length());
3247 } else if (s.begins_with("/") || s.begins_with("\\")) {
3248
3249 drive = s.substr(0, 1);
3250 s = s.substr(1, s.length() - 1);
3251 } else {
3252
3253 int p = s.find(":/");
3254 if (p == -1)
3255 p = s.find(":\\");
3256 if (p != -1 && p < s.find("/")) {
3257
3258 drive = s.substr(0, p + 2);
3259 s = s.substr(p + 2, s.length());
3260 }
3261 }
3262
3263 s = s.replace("\\", "/");
3264 while (true) { // in case of using 2 or more slash
3265 String compare = s.replace("//", "/");
3266 if (s == compare)
3267 break;
3268 else
3269 s = compare;
3270 }
3271 Vector<String> dirs = s.split("/", false);
3272
3273 for (int i = 0; i < dirs.size(); i++) {
3274
3275 String d = dirs[i];
3276 if (d == ".") {
3277 dirs.remove(i);
3278 i--;
3279 } else if (d == "..") {
3280
3281 if (i == 0) {
3282 dirs.remove(i);
3283 i--;
3284 } else {
3285 dirs.remove(i);
3286 dirs.remove(i - 1);
3287 i -= 2;
3288 }
3289 }
3290 }
3291
3292 s = "";
3293
3294 for (int i = 0; i < dirs.size(); i++) {
3295
3296 if (i > 0)
3297 s += "/";
3298 s += dirs[i];
3299 }
3300
3301 return drive + s;
3302 }
3303
_humanize_digits(int p_num)3304 static int _humanize_digits(int p_num) {
3305
3306 if (p_num < 100)
3307 return 2;
3308 else if (p_num < 1024)
3309 return 1;
3310 else
3311 return 0;
3312 }
3313
humanize_size(uint64_t p_size)3314 String String::humanize_size(uint64_t p_size) {
3315
3316 uint64_t _div = 1;
3317 Vector<String> prefixes;
3318 prefixes.push_back(RTR("B"));
3319 prefixes.push_back(RTR("KiB"));
3320 prefixes.push_back(RTR("MiB"));
3321 prefixes.push_back(RTR("GiB"));
3322 prefixes.push_back(RTR("TiB"));
3323 prefixes.push_back(RTR("PiB"));
3324 prefixes.push_back(RTR("EiB"));
3325
3326 int prefix_idx = 0;
3327
3328 while (prefix_idx < prefixes.size() - 1 && p_size > (_div * 1024)) {
3329 _div *= 1024;
3330 prefix_idx++;
3331 }
3332
3333 const int digits = prefix_idx > 0 ? _humanize_digits(p_size / _div) : 0;
3334 const double divisor = prefix_idx > 0 ? _div : 1;
3335
3336 return String::num(p_size / divisor).pad_decimals(digits) + " " + prefixes[prefix_idx];
3337 }
is_abs_path() const3338 bool String::is_abs_path() const {
3339
3340 if (length() > 1)
3341 return (operator[](0) == '/' || operator[](0) == '\\' || find(":/") != -1 || find(":\\") != -1);
3342 else if ((length()) == 1)
3343 return (operator[](0) == '/' || operator[](0) == '\\');
3344 else
3345 return false;
3346 }
3347
is_valid_identifier() const3348 bool String::is_valid_identifier() const {
3349
3350 int len = length();
3351
3352 if (len == 0)
3353 return false;
3354
3355 const wchar_t *str = &operator[](0);
3356
3357 for (int i = 0; i < len; i++) {
3358
3359 if (i == 0) {
3360 if (str[0] >= '0' && str[0] <= '9')
3361 return false; // no start with number plz
3362 }
3363
3364 bool valid_char = (str[i] >= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || str[i] == '_';
3365
3366 if (!valid_char)
3367 return false;
3368 }
3369
3370 return true;
3371 }
3372
3373 //kind of poor should be rewritten properly
3374
word_wrap(int p_chars_per_line) const3375 String String::word_wrap(int p_chars_per_line) const {
3376
3377 int from = 0;
3378 int last_space = 0;
3379 String ret;
3380 for (int i = 0; i < length(); i++) {
3381 if (i - from >= p_chars_per_line) {
3382 if (last_space == -1) {
3383 ret += substr(from, i - from + 1) + "\n";
3384 } else {
3385 ret += substr(from, last_space - from) + "\n";
3386 i = last_space; //rewind
3387 }
3388 from = i + 1;
3389 last_space = -1;
3390 } else if (operator[](i) == ' ' || operator[](i) == '\t') {
3391 last_space = i;
3392 } else if (operator[](i) == '\n') {
3393 ret += substr(from, i - from) + "\n";
3394 from = i + 1;
3395 last_space = -1;
3396 }
3397 }
3398
3399 if (from < length()) {
3400 ret += substr(from, length());
3401 }
3402
3403 return ret;
3404 }
3405
http_escape() const3406 String String::http_escape() const {
3407 const CharString temp = utf8();
3408 String res;
3409 for (int i = 0; i < temp.length(); ++i) {
3410 char ord = temp[i];
3411 if (ord == '.' || ord == '-' || ord == '_' || ord == '~' ||
3412 (ord >= 'a' && ord <= 'z') ||
3413 (ord >= 'A' && ord <= 'Z') ||
3414 (ord >= '0' && ord <= '9')) {
3415 res += ord;
3416 } else {
3417 char h_Val[3];
3418 #if defined(__GNUC__) || defined(_MSC_VER)
3419 snprintf(h_Val, 3, "%hhX", ord);
3420 #else
3421 sprintf(h_Val, "%hhX", ord);
3422 #endif
3423 res += "%";
3424 res += h_Val;
3425 }
3426 }
3427 return res;
3428 }
3429
http_unescape() const3430 String String::http_unescape() const {
3431 String res;
3432 for (int i = 0; i < length(); ++i) {
3433 if (ord_at(i) == '%' && i + 2 < length()) {
3434 CharType ord1 = ord_at(i + 1);
3435 if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) {
3436 CharType ord2 = ord_at(i + 2);
3437 if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) {
3438 char bytes[3] = { (char)ord1, (char)ord2, 0 };
3439 res += (char)strtol(bytes, NULL, 16);
3440 i += 2;
3441 }
3442 } else {
3443 res += ord_at(i);
3444 }
3445 } else {
3446 res += ord_at(i);
3447 }
3448 }
3449 return String::utf8(res.ascii());
3450 }
3451
c_unescape() const3452 String String::c_unescape() const {
3453
3454 String escaped = *this;
3455 escaped = escaped.replace("\\a", "\a");
3456 escaped = escaped.replace("\\b", "\b");
3457 escaped = escaped.replace("\\f", "\f");
3458 escaped = escaped.replace("\\n", "\n");
3459 escaped = escaped.replace("\\r", "\r");
3460 escaped = escaped.replace("\\t", "\t");
3461 escaped = escaped.replace("\\v", "\v");
3462 escaped = escaped.replace("\\'", "\'");
3463 escaped = escaped.replace("\\\"", "\"");
3464 escaped = escaped.replace("\\?", "\?");
3465 escaped = escaped.replace("\\\\", "\\");
3466
3467 return escaped;
3468 }
3469
c_escape() const3470 String String::c_escape() const {
3471
3472 String escaped = *this;
3473 escaped = escaped.replace("\\", "\\\\");
3474 escaped = escaped.replace("\a", "\\a");
3475 escaped = escaped.replace("\b", "\\b");
3476 escaped = escaped.replace("\f", "\\f");
3477 escaped = escaped.replace("\n", "\\n");
3478 escaped = escaped.replace("\r", "\\r");
3479 escaped = escaped.replace("\t", "\\t");
3480 escaped = escaped.replace("\v", "\\v");
3481 escaped = escaped.replace("\'", "\\'");
3482 escaped = escaped.replace("\?", "\\?");
3483 escaped = escaped.replace("\"", "\\\"");
3484
3485 return escaped;
3486 }
3487
c_escape_multiline() const3488 String String::c_escape_multiline() const {
3489
3490 String escaped = *this;
3491 escaped = escaped.replace("\\", "\\\\");
3492 escaped = escaped.replace("\"", "\\\"");
3493
3494 return escaped;
3495 }
3496
json_escape() const3497 String String::json_escape() const {
3498
3499 String escaped = *this;
3500 escaped = escaped.replace("\\", "\\\\");
3501 escaped = escaped.replace("\b", "\\b");
3502 escaped = escaped.replace("\f", "\\f");
3503 escaped = escaped.replace("\n", "\\n");
3504 escaped = escaped.replace("\r", "\\r");
3505 escaped = escaped.replace("\t", "\\t");
3506 escaped = escaped.replace("\v", "\\v");
3507 escaped = escaped.replace("\"", "\\\"");
3508
3509 return escaped;
3510 }
3511
xml_escape(bool p_escape_quotes) const3512 String String::xml_escape(bool p_escape_quotes) const {
3513
3514 String str = *this;
3515 str = str.replace("&", "&");
3516 str = str.replace("<", "<");
3517 str = str.replace(">", ">");
3518 if (p_escape_quotes) {
3519 str = str.replace("'", "'");
3520 str = str.replace("\"", """);
3521 }
3522 /*
3523 for (int i=1;i<32;i++) {
3524
3525 char chr[2]={i,0};
3526 str=str.replace(chr,"&#"+String::num(i)+";");
3527 }*/
3528 return str;
3529 }
3530
_xml_unescape(const CharType * p_src,int p_src_len,CharType * p_dst)3531 static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, CharType *p_dst) {
3532
3533 int len = 0;
3534 while (p_src_len) {
3535
3536 if (*p_src == '&') {
3537
3538 int eat = 0;
3539
3540 if (p_src_len >= 4 && p_src[1] == '#') {
3541
3542 CharType c = 0;
3543
3544 for (int i = 2; i < p_src_len; i++) {
3545
3546 eat = i + 1;
3547 CharType ct = p_src[i];
3548 if (ct == ';') {
3549 break;
3550 } else if (ct >= '0' && ct <= '9') {
3551 ct = ct - '0';
3552 } else if (ct >= 'a' && ct <= 'f') {
3553 ct = (ct - 'a') + 10;
3554 } else if (ct >= 'A' && ct <= 'F') {
3555 ct = (ct - 'A') + 10;
3556 } else {
3557 continue;
3558 }
3559 c <<= 4;
3560 c |= ct;
3561 }
3562
3563 if (p_dst)
3564 *p_dst = c;
3565
3566 } else if (p_src_len >= 4 && p_src[1] == 'g' && p_src[2] == 't' && p_src[3] == ';') {
3567
3568 if (p_dst)
3569 *p_dst = '>';
3570 eat = 4;
3571 } else if (p_src_len >= 4 && p_src[1] == 'l' && p_src[2] == 't' && p_src[3] == ';') {
3572
3573 if (p_dst)
3574 *p_dst = '<';
3575 eat = 4;
3576 } else if (p_src_len >= 5 && p_src[1] == 'a' && p_src[2] == 'm' && p_src[3] == 'p' && p_src[4] == ';') {
3577
3578 if (p_dst)
3579 *p_dst = '&';
3580 eat = 5;
3581 } else if (p_src_len >= 6 && p_src[1] == 'q' && p_src[2] == 'u' && p_src[3] == 'o' && p_src[4] == 't' && p_src[5] == ';') {
3582
3583 if (p_dst)
3584 *p_dst = '"';
3585 eat = 6;
3586 } else if (p_src_len >= 6 && p_src[1] == 'a' && p_src[2] == 'p' && p_src[3] == 'o' && p_src[4] == 's' && p_src[5] == ';') {
3587
3588 if (p_dst)
3589 *p_dst = '\'';
3590 eat = 6;
3591 } else {
3592
3593 if (p_dst)
3594 *p_dst = *p_src;
3595 eat = 1;
3596 }
3597
3598 if (p_dst)
3599 p_dst++;
3600
3601 len++;
3602 p_src += eat;
3603 p_src_len -= eat;
3604 } else {
3605
3606 if (p_dst) {
3607 *p_dst = *p_src;
3608 p_dst++;
3609 }
3610 len++;
3611 p_src++;
3612 p_src_len--;
3613 }
3614 }
3615
3616 return len;
3617 }
3618
xml_unescape() const3619 String String::xml_unescape() const {
3620
3621 String str;
3622 int l = length();
3623 int len = _xml_unescape(c_str(), l, NULL);
3624 if (len == 0)
3625 return String();
3626 str.resize(len + 1);
3627 _xml_unescape(c_str(), l, str.ptrw());
3628 str[len] = 0;
3629 return str;
3630 }
3631
pad_decimals(int p_digits) const3632 String String::pad_decimals(int p_digits) const {
3633
3634 String s = *this;
3635 int c = s.find(".");
3636
3637 if (c == -1) {
3638 if (p_digits <= 0) {
3639 return s;
3640 }
3641 s += ".";
3642 c = s.length() - 1;
3643 } else {
3644 if (p_digits <= 0) {
3645 return s.substr(0, c);
3646 }
3647 }
3648
3649 if (s.length() - (c + 1) > p_digits) {
3650 s = s.substr(0, c + p_digits + 1);
3651 } else {
3652 while (s.length() - (c + 1) < p_digits) {
3653 s += "0";
3654 }
3655 }
3656 return s;
3657 }
3658
pad_zeros(int p_digits) const3659 String String::pad_zeros(int p_digits) const {
3660
3661 String s = *this;
3662 int end = s.find(".");
3663
3664 if (end == -1) {
3665 end = s.length();
3666 }
3667
3668 if (end == 0)
3669 return s;
3670
3671 int begin = 0;
3672
3673 while (begin < end && (s[begin] < '0' || s[begin] > '9')) {
3674 begin++;
3675 }
3676
3677 if (begin >= end)
3678 return s;
3679
3680 while (end - begin < p_digits) {
3681
3682 s = s.insert(begin, "0");
3683 end++;
3684 }
3685
3686 return s;
3687 }
3688
trim_prefix(const String & p_prefix) const3689 String String::trim_prefix(const String &p_prefix) const {
3690
3691 String s = *this;
3692 if (s.begins_with(p_prefix)) {
3693 return s.substr(p_prefix.length(), s.length() - p_prefix.length());
3694 }
3695 return s;
3696 }
3697
trim_suffix(const String & p_suffix) const3698 String String::trim_suffix(const String &p_suffix) const {
3699
3700 String s = *this;
3701 if (s.ends_with(p_suffix)) {
3702 return s.substr(0, s.length() - p_suffix.length());
3703 }
3704 return s;
3705 }
3706
is_valid_integer() const3707 bool String::is_valid_integer() const {
3708
3709 int len = length();
3710
3711 if (len == 0)
3712 return false;
3713
3714 int from = 0;
3715 if (len != 1 && (operator[](0) == '+' || operator[](0) == '-'))
3716 from++;
3717
3718 for (int i = from; i < len; i++) {
3719
3720 if (operator[](i) < '0' || operator[](i) > '9')
3721 return false; // no start with number plz
3722 }
3723
3724 return true;
3725 }
3726
is_valid_hex_number(bool p_with_prefix) const3727 bool String::is_valid_hex_number(bool p_with_prefix) const {
3728
3729 int len = length();
3730
3731 if (len == 0)
3732 return false;
3733
3734 int from = 0;
3735 if (len != 1 && (operator[](0) == '+' || operator[](0) == '-'))
3736 from++;
3737
3738 if (p_with_prefix) {
3739
3740 if (len < 3)
3741 return false;
3742 if (operator[](from) != '0' || operator[](from + 1) != 'x') {
3743 return false;
3744 }
3745 from += 2;
3746 }
3747
3748 for (int i = from; i < len; i++) {
3749
3750 CharType c = operator[](i);
3751 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
3752 continue;
3753 return false;
3754 }
3755
3756 return true;
3757 };
3758
is_valid_float() const3759 bool String::is_valid_float() const {
3760
3761 int len = length();
3762
3763 if (len == 0)
3764 return false;
3765
3766 int from = 0;
3767 if (operator[](0) == '+' || operator[](0) == '-') {
3768 from++;
3769 }
3770
3771 bool exponent_found = false;
3772 bool period_found = false;
3773 bool sign_found = false;
3774 bool exponent_values_found = false;
3775 bool numbers_found = false;
3776
3777 for (int i = from; i < len; i++) {
3778
3779 if (operator[](i) >= '0' && operator[](i) <= '9') {
3780
3781 if (exponent_found)
3782 exponent_values_found = true;
3783 else
3784 numbers_found = true;
3785 } else if (numbers_found && !exponent_found && operator[](i) == 'e') {
3786 exponent_found = true;
3787 } else if (!period_found && !exponent_found && operator[](i) == '.') {
3788 period_found = true;
3789 } else if ((operator[](i) == '-' || operator[](i) == '+') && exponent_found && !exponent_values_found && !sign_found) {
3790 sign_found = true;
3791 } else
3792 return false; // no start with number plz
3793 }
3794
3795 return numbers_found;
3796 }
3797
path_to_file(const String & p_path) const3798 String String::path_to_file(const String &p_path) const {
3799
3800 // Don't get base dir for src, this is expected to be a dir already.
3801 String src = this->replace("\\", "/");
3802 String dst = p_path.replace("\\", "/").get_base_dir();
3803 String rel = src.path_to(dst);
3804 if (rel == dst) // failed
3805 return p_path;
3806 else
3807 return rel + p_path.get_file();
3808 }
3809
path_to(const String & p_path) const3810 String String::path_to(const String &p_path) const {
3811
3812 String src = this->replace("\\", "/");
3813 String dst = p_path.replace("\\", "/");
3814 if (!src.ends_with("/"))
3815 src += "/";
3816 if (!dst.ends_with("/"))
3817 dst += "/";
3818
3819 String base;
3820
3821 if (src.begins_with("res://") && dst.begins_with("res://")) {
3822
3823 base = "res:/";
3824 src = src.replace("res://", "/");
3825 dst = dst.replace("res://", "/");
3826
3827 } else if (src.begins_with("user://") && dst.begins_with("user://")) {
3828
3829 base = "user:/";
3830 src = src.replace("user://", "/");
3831 dst = dst.replace("user://", "/");
3832
3833 } else if (src.begins_with("/") && dst.begins_with("/")) {
3834
3835 //nothing
3836 } else {
3837 //dos style
3838 String src_begin = src.get_slicec('/', 0);
3839 String dst_begin = dst.get_slicec('/', 0);
3840
3841 if (src_begin != dst_begin)
3842 return p_path; //impossible to do this
3843
3844 base = src_begin;
3845 src = src.substr(src_begin.length(), src.length());
3846 dst = dst.substr(dst_begin.length(), dst.length());
3847 }
3848
3849 //remove leading and trailing slash and split
3850 Vector<String> src_dirs = src.substr(1, src.length() - 2).split("/");
3851 Vector<String> dst_dirs = dst.substr(1, dst.length() - 2).split("/");
3852
3853 //find common parent
3854 int common_parent = 0;
3855
3856 while (true) {
3857 if (src_dirs.size() == common_parent)
3858 break;
3859 if (dst_dirs.size() == common_parent)
3860 break;
3861 if (src_dirs[common_parent] != dst_dirs[common_parent])
3862 break;
3863 common_parent++;
3864 }
3865
3866 common_parent--;
3867
3868 String dir;
3869
3870 for (int i = src_dirs.size() - 1; i > common_parent; i--) {
3871
3872 dir += "../";
3873 }
3874
3875 for (int i = common_parent + 1; i < dst_dirs.size(); i++) {
3876
3877 dir += dst_dirs[i] + "/";
3878 }
3879
3880 if (dir.length() == 0)
3881 dir = "./";
3882 return dir;
3883 }
3884
is_valid_html_color() const3885 bool String::is_valid_html_color() const {
3886
3887 return Color::html_is_valid(*this);
3888 }
3889
is_valid_filename() const3890 bool String::is_valid_filename() const {
3891
3892 String stripped = strip_edges();
3893 if (*this != stripped) {
3894 return false;
3895 }
3896
3897 if (stripped == String()) {
3898 return false;
3899 }
3900
3901 return !(find(":") != -1 || find("/") != -1 || find("\\") != -1 || find("?") != -1 || find("*") != -1 || find("\"") != -1 || find("|") != -1 || find("%") != -1 || find("<") != -1 || find(">") != -1);
3902 }
3903
is_valid_ip_address() const3904 bool String::is_valid_ip_address() const {
3905
3906 if (find(":") >= 0) {
3907
3908 Vector<String> ip = split(":");
3909 for (int i = 0; i < ip.size(); i++) {
3910
3911 String n = ip[i];
3912 if (n.empty())
3913 continue;
3914 if (n.is_valid_hex_number(false)) {
3915 int nint = n.hex_to_int(false);
3916 if (nint < 0 || nint > 0xffff)
3917 return false;
3918 continue;
3919 };
3920 if (!n.is_valid_ip_address())
3921 return false;
3922 };
3923
3924 } else {
3925 Vector<String> ip = split(".");
3926 if (ip.size() != 4)
3927 return false;
3928 for (int i = 0; i < ip.size(); i++) {
3929
3930 String n = ip[i];
3931 if (!n.is_valid_integer())
3932 return false;
3933 int val = n.to_int();
3934 if (val < 0 || val > 255)
3935 return false;
3936 }
3937 };
3938
3939 return true;
3940 }
3941
is_resource_file() const3942 bool String::is_resource_file() const {
3943
3944 return begins_with("res://") && find("::") == -1;
3945 }
3946
is_rel_path() const3947 bool String::is_rel_path() const {
3948
3949 return !is_abs_path();
3950 }
3951
get_base_dir() const3952 String String::get_base_dir() const {
3953
3954 int basepos = find("://");
3955 String rs;
3956 String base;
3957 if (basepos != -1) {
3958 int end = basepos + 3;
3959 rs = substr(end, length());
3960 base = substr(0, end);
3961 } else {
3962 if (begins_with("/")) {
3963 rs = substr(1, length());
3964 base = "/";
3965 } else {
3966
3967 rs = *this;
3968 }
3969 }
3970
3971 int sep = MAX(rs.find_last("/"), rs.find_last("\\"));
3972 if (sep == -1)
3973 return base;
3974
3975 return base + rs.substr(0, sep);
3976 }
3977
get_file() const3978 String String::get_file() const {
3979
3980 int sep = MAX(find_last("/"), find_last("\\"));
3981 if (sep == -1)
3982 return *this;
3983
3984 return substr(sep + 1, length());
3985 }
3986
get_extension() const3987 String String::get_extension() const {
3988
3989 int pos = find_last(".");
3990 if (pos < 0 || pos < MAX(find_last("/"), find_last("\\")))
3991 return "";
3992
3993 return substr(pos + 1, length());
3994 }
3995
plus_file(const String & p_file) const3996 String String::plus_file(const String &p_file) const {
3997 if (empty())
3998 return p_file;
3999 if (operator[](length() - 1) == '/' || (p_file.size() > 0 && p_file.operator[](0) == '/'))
4000 return *this + p_file;
4001 return *this + "/" + p_file;
4002 }
4003
percent_encode() const4004 String String::percent_encode() const {
4005
4006 CharString cs = utf8();
4007 String encoded;
4008 for (int i = 0; i < cs.length(); i++) {
4009 uint8_t c = cs[i];
4010 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '.') {
4011
4012 char p[2] = { (char)c, 0 };
4013 encoded += p;
4014 } else {
4015 char p[4] = { '%', 0, 0, 0 };
4016 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
4017
4018 p[1] = hex[c >> 4];
4019 p[2] = hex[c & 0xF];
4020 encoded += p;
4021 }
4022 }
4023
4024 return encoded;
4025 }
percent_decode() const4026 String String::percent_decode() const {
4027
4028 CharString pe;
4029
4030 CharString cs = utf8();
4031 for (int i = 0; i < cs.length(); i++) {
4032
4033 uint8_t c = cs[i];
4034 if (c == '%' && i < length() - 2) {
4035
4036 uint8_t a = LOWERCASE(cs[i + 1]);
4037 uint8_t b = LOWERCASE(cs[i + 2]);
4038
4039 if (a >= '0' && a <= '9')
4040 c = (a - '0') << 4;
4041 else if (a >= 'a' && a <= 'f')
4042 c = (a - 'a' + 10) << 4;
4043 else
4044 continue;
4045
4046 uint8_t d = 0;
4047
4048 if (b >= '0' && b <= '9')
4049 d = (b - '0');
4050 else if (b >= 'a' && b <= 'f')
4051 d = (b - 'a' + 10);
4052 else
4053 continue;
4054 c += d;
4055 i += 2;
4056 }
4057 pe += c;
4058 }
4059
4060 return String::utf8(pe.ptr());
4061 }
4062
property_name_encode() const4063 String String::property_name_encode() const {
4064 // Escape and quote strings with extended ASCII or further Unicode characters
4065 // as well as '"', '=' or ' ' (32)
4066 const CharType *cstr = c_str();
4067 for (int i = 0; cstr[i]; i++) {
4068 if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) {
4069 return "\"" + c_escape_multiline() + "\"";
4070 }
4071 }
4072 // Keep as is
4073 return *this;
4074 }
4075
get_basename() const4076 String String::get_basename() const {
4077
4078 int pos = find_last(".");
4079 if (pos < 0 || pos < MAX(find_last("/"), find_last("\\")))
4080 return *this;
4081
4082 return substr(0, pos);
4083 }
4084
itos(int64_t p_val)4085 String itos(int64_t p_val) {
4086
4087 return String::num_int64(p_val);
4088 }
4089
uitos(uint64_t p_val)4090 String uitos(uint64_t p_val) {
4091
4092 return String::num_uint64(p_val);
4093 }
4094
rtos(double p_val)4095 String rtos(double p_val) {
4096
4097 return String::num(p_val);
4098 }
4099
rtoss(double p_val)4100 String rtoss(double p_val) {
4101
4102 return String::num_scientific(p_val);
4103 }
4104
4105 // Right-pad with a character.
rpad(int min_length,const String & character) const4106 String String::rpad(int min_length, const String &character) const {
4107 String s = *this;
4108 int padding = min_length - s.length();
4109 if (padding > 0) {
4110 for (int i = 0; i < padding; i++)
4111 s = s + character;
4112 }
4113
4114 return s;
4115 }
4116 // Left-pad with a character.
lpad(int min_length,const String & character) const4117 String String::lpad(int min_length, const String &character) const {
4118 String s = *this;
4119 int padding = min_length - s.length();
4120 if (padding > 0) {
4121 for (int i = 0; i < padding; i++)
4122 s = character + s;
4123 }
4124
4125 return s;
4126 }
4127
4128 // sprintf is implemented in GDScript via:
4129 // "fish %s pie" % "frog"
4130 // "fish %s %d pie" % ["frog", 12]
4131 // In case of an error, the string returned is the error description and "error" is true.
sprintf(const Array & values,bool * error) const4132 String String::sprintf(const Array &values, bool *error) const {
4133 String formatted;
4134 CharType *self = (CharType *)c_str();
4135 bool in_format = false;
4136 int value_index = 0;
4137 int min_chars = 0;
4138 int min_decimals = 0;
4139 bool in_decimals = false;
4140 bool pad_with_zeroes = false;
4141 bool left_justified = false;
4142 bool show_sign = false;
4143
4144 *error = true;
4145
4146 for (; *self; self++) {
4147 const CharType c = *self;
4148
4149 if (in_format) { // We have % - lets see what else we get.
4150 switch (c) {
4151 case '%': { // Replace %% with %
4152 formatted += chr(c);
4153 in_format = false;
4154 break;
4155 }
4156 case 'd': // Integer (signed)
4157 case 'o': // Octal
4158 case 'x': // Hexadecimal (lowercase)
4159 case 'X': { // Hexadecimal (uppercase)
4160 if (value_index >= values.size()) {
4161 return "not enough arguments for format string";
4162 }
4163
4164 if (!values[value_index].is_num()) {
4165 return "a number is required";
4166 }
4167
4168 int64_t value = values[value_index];
4169 int base = 16;
4170 bool capitalize = false;
4171 switch (c) {
4172 case 'd': base = 10; break;
4173 case 'o': base = 8; break;
4174 case 'x': break;
4175 case 'X':
4176 base = 16;
4177 capitalize = true;
4178 break;
4179 }
4180 // Get basic number.
4181 String str = String::num_int64(ABS(value), base, capitalize);
4182 int number_len = str.length();
4183
4184 // Padding.
4185 String pad_char = pad_with_zeroes ? String("0") : String(" ");
4186 if (left_justified) {
4187 str = str.rpad(min_chars, pad_char);
4188 } else {
4189 str = str.lpad(min_chars, pad_char);
4190 }
4191
4192 // Sign.
4193 if (show_sign && value >= 0) {
4194 str = str.insert(pad_with_zeroes ? 0 : str.length() - number_len, "+");
4195 } else if (value < 0) {
4196 str = str.insert(pad_with_zeroes ? 0 : str.length() - number_len, "-");
4197 }
4198
4199 formatted += str;
4200 ++value_index;
4201 in_format = false;
4202
4203 break;
4204 }
4205 case 'f': { // Float
4206 if (value_index >= values.size()) {
4207 return "not enough arguments for format string";
4208 }
4209
4210 if (!values[value_index].is_num()) {
4211 return "a number is required";
4212 }
4213
4214 double value = values[value_index];
4215 bool is_negative = (value < 0);
4216 String str = String::num(ABS(value), min_decimals);
4217
4218 // Pad decimals out.
4219 str = str.pad_decimals(min_decimals);
4220
4221 int initial_len = str.length();
4222
4223 // Padding. Leave room for sign later if required.
4224 int pad_chars_count = (is_negative || show_sign) ? min_chars - 1 : min_chars;
4225 String pad_char = pad_with_zeroes ? String("0") : String(" ");
4226 if (left_justified) {
4227 if (pad_with_zeroes) {
4228 return "left justification cannot be used with zeros as the padding";
4229 } else {
4230 str = str.rpad(pad_chars_count, pad_char);
4231 }
4232 } else {
4233 str = str.lpad(pad_chars_count, pad_char);
4234 }
4235
4236 // Add sign if needed.
4237 if (show_sign || is_negative) {
4238 String sign_char = is_negative ? "-" : "+";
4239 if (left_justified) {
4240 str = str.insert(0, sign_char);
4241 } else {
4242 str = str.insert(pad_with_zeroes ? 0 : str.length() - initial_len, sign_char);
4243 }
4244 }
4245
4246 formatted += str;
4247 ++value_index;
4248 in_format = false;
4249 break;
4250 }
4251 case 's': { // String
4252 if (value_index >= values.size()) {
4253 return "not enough arguments for format string";
4254 }
4255
4256 String str = values[value_index];
4257 // Padding.
4258 if (left_justified) {
4259 str = str.rpad(min_chars);
4260 } else {
4261 str = str.lpad(min_chars);
4262 }
4263
4264 formatted += str;
4265 ++value_index;
4266 in_format = false;
4267 break;
4268 }
4269 case 'c': {
4270 if (value_index >= values.size()) {
4271 return "not enough arguments for format string";
4272 }
4273
4274 // Convert to character.
4275 String str;
4276 if (values[value_index].is_num()) {
4277 int value = values[value_index];
4278 if (value < 0) {
4279 return "unsigned byte integer is lower than maximum";
4280 } else if (value > 255) {
4281 return "unsigned byte integer is greater than maximum";
4282 }
4283 str = chr(values[value_index]);
4284 } else if (values[value_index].get_type() == Variant::STRING) {
4285 str = values[value_index];
4286 if (str.length() != 1) {
4287 return "%c requires number or single-character string";
4288 }
4289 } else {
4290 return "%c requires number or single-character string";
4291 }
4292
4293 // Padding.
4294 if (left_justified) {
4295 str = str.rpad(min_chars);
4296 } else {
4297 str = str.lpad(min_chars);
4298 }
4299
4300 formatted += str;
4301 ++value_index;
4302 in_format = false;
4303 break;
4304 }
4305 case '-': { // Left justify
4306 left_justified = true;
4307 break;
4308 }
4309 case '+': { // Show + if positive.
4310 show_sign = true;
4311 break;
4312 }
4313 case '0':
4314 case '1':
4315 case '2':
4316 case '3':
4317 case '4':
4318 case '5':
4319 case '6':
4320 case '7':
4321 case '8':
4322 case '9': {
4323 int n = c - '0';
4324 if (in_decimals) {
4325 min_decimals *= 10;
4326 min_decimals += n;
4327 } else {
4328 if (c == '0' && min_chars == 0) {
4329 pad_with_zeroes = true;
4330 } else {
4331 min_chars *= 10;
4332 min_chars += n;
4333 }
4334 }
4335 break;
4336 }
4337 case '.': { // Float separator.
4338 if (in_decimals) {
4339 return "too many decimal points in format";
4340 }
4341 in_decimals = true;
4342 min_decimals = 0; // We want to add the value manually.
4343 break;
4344 }
4345
4346 case '*': { // Dynamic width, based on value.
4347 if (value_index >= values.size()) {
4348 return "not enough arguments for format string";
4349 }
4350
4351 if (!values[value_index].is_num()) {
4352 return "* wants number";
4353 }
4354
4355 int size = values[value_index];
4356
4357 if (in_decimals) {
4358 min_decimals = size;
4359 } else {
4360 min_chars = size;
4361 }
4362
4363 ++value_index;
4364 break;
4365 }
4366
4367 default: {
4368 return "unsupported format character";
4369 }
4370 }
4371 } else { // Not in format string.
4372 switch (c) {
4373 case '%':
4374 in_format = true;
4375 // Back to defaults:
4376 min_chars = 0;
4377 min_decimals = 6;
4378 pad_with_zeroes = false;
4379 left_justified = false;
4380 show_sign = false;
4381 in_decimals = false;
4382 break;
4383 default:
4384 formatted += chr(c);
4385 }
4386 }
4387 }
4388
4389 if (in_format) {
4390 return "incomplete format";
4391 }
4392
4393 if (value_index != values.size()) {
4394 return "not all arguments converted during string formatting";
4395 }
4396
4397 *error = false;
4398 return formatted;
4399 }
4400
quote(String quotechar) const4401 String String::quote(String quotechar) const {
4402 return quotechar + *this + quotechar;
4403 }
4404
unquote() const4405 String String::unquote() const {
4406 if (!is_quoted()) {
4407 return *this;
4408 }
4409
4410 return substr(1, length() - 2);
4411 }
4412
4413 #ifdef TOOLS_ENABLED
TTR(const String & p_text)4414 String TTR(const String &p_text) {
4415
4416 if (TranslationServer::get_singleton()) {
4417 return TranslationServer::get_singleton()->tool_translate(p_text);
4418 }
4419
4420 return p_text;
4421 }
4422
4423 #endif
4424
RTR(const String & p_text)4425 String RTR(const String &p_text) {
4426
4427 if (TranslationServer::get_singleton()) {
4428 String rtr = TranslationServer::get_singleton()->tool_translate(p_text);
4429 if (rtr == String() || rtr == p_text) {
4430 return TranslationServer::get_singleton()->translate(p_text);
4431 } else {
4432 return rtr;
4433 }
4434 }
4435
4436 return p_text;
4437 }
4438