EHS
Str.h
Go to the documentation of this file.
1#pragma once
2
3#include "Types.h"
4#include "BaseObj.h"
5#include "Util.h"
6#include "Vector.h"
7
8#include <utility>
9
10namespace ehs
11{
12 enum class SearchPattern
13 {
16 };
17
18 enum class IndexResult
19 {
21 ENDING
22 };
23
27 template<typename T = Char_8, typename N = UInt_64>
28 class Str
29 {
30 private:
31 N size;
32 T* data;
33
34 public:
37 {
38 delete[] data;
39 }
40
43 : size(0), data(nullptr)
44 {
45 }
46
50 Str(const T* const str, const N size)
51 : size((size) ? size : Len(str)), data(nullptr)
52 {
53 data = new T[this->size + 1];
54
55 Util::Copy(data, str, Size(true));
56
57 data[this->size] = 0;
58 }
59
62 Str(const T* const str)
63 : size(Len(str)), data(nullptr)
64 {
65 data = new T[size + 1];
66
67 Util::Copy(data, str, Size(true));
68
69 data[size] = 0;
70 }
71
74 Str(const N size)
75 : size(size), data(new T[size + 1])
76 {
77 data[size] = 0;
78 }
79
81 Str(Str&& str) noexcept
82 : size(str.size), data(str.data)
83 {
84 str.size = 0;
85 str.data = nullptr;
86 }
87
90 Str(const Str& str)
91 : size(str.size), data(new T[size + 1])
92 {
93 Util::Copy(data, str.data, Size(true));
94
95 data[size] = 0;
96 }
97
98 Str& operator=(Str&& str) noexcept
99 {
100 if (this == &str)
101 return *this;
102
103 size = str.size;
104 delete[] data;
105 data = str.data;
106
107 str.size = 0;
108 str.data = nullptr;
109
110 return *this;
111 }
112
116 Str& operator=(const Str& str)
117 {
118 if (&str == this)
119 return *this;
120
121 size = str.size;
122
123 delete[] data;
124 data = new T[size + 1];
125 Util::Copy(data, str.data, Size(true));
126 data[size] = 0;
127
128 return *this;
129 }
130
134 Str<T, N>& operator=(const T* const str)
135 {
136 size = Len(str);
137
138 delete[] data;
139
140 data = new T[size + 1];
141
142 Util::Copy(data, str, Size(true));
143
144 data[size] = 0;
145
146 return *this;
147 }
148
152 Str<T, N>& operator+=(const T* const str)
153 {
154 N inputSize = Len(str);
155
156 T* result = new T[size + inputSize + 1];
157
158 Util::Copy(result, data, Size(true));
159
160 delete[] data;
161
162 Util::Copy(&result[size], str, inputSize * sizeof(T));
163
164 result[size + inputSize] = 0;
165 size += inputSize;
166 data = result;
167
168 return *this;
169 }
170
175 {
176 T* result = new T[size + str.size + 1];
177
178 Util::Copy(result, data, Size(true));
179
180 delete[] data;
181
182 Util::Copy(&result[size], str, str.Size(true));
183
184 result[size + str.size] = 0;
185 size += str.Size();
186 data = result;
187
188 return *this;
189 }
190
194 Str<T, N>& operator+=(const SInt_64 num)
195 {
196 return operator+=(FromNum(num));
197 }
198
202 Str<T, N>& operator+=(const UInt_64 num)
203 {
204 return operator+=(FromNum(num));
205 }
206
211 {
212 return operator+=(FromNum(num));
213 }
214
219 {
220 return operator+=(FromNum(num));
221 }
222
227 {
228 return operator+=(FromNum(num));
229 }
230
235 {
236 return operator+=(FromNum(num));
237 }
238
243 {
244 return operator+=(FromNum(num));
245 }
246
251 {
252 return operator+=(FromNum(num));
253 }
254
255 #ifdef EHS_OS_WINDOWS
259 Str<T, N>& operator+=(const DWORD num)
260 {
261 return operator+=(FromNum(num));
262 }
263
267 Str<T, N>& operator+=(const HRESULT num)
268 {
269 return operator+=(FromNum(num));
270 }
271 #endif
272
276 Str<T, N>& operator+=(const float num)
277 {
278 return operator+=(FromNum(num));
279 }
280
284 Str<T, N>& operator+=(const double num)
285 {
286 return operator+=(FromNum(num));
287 }
288
292 Str<T, N>& operator+=(const long double num)
293 {
294 return operator+=(FromNum(num));
295 }
296
300 Str<T, N> operator+(const T* const str) const
301 {
302 N inSize = Len(str);
303
304 Str<T, N> result(size + inSize);
305
306 Util::Copy(result.data, data, Size(true));
307
308 Util::Copy(&result.data[size], str, inSize * sizeof(T));
309
310 result.data[size + inSize] = 0;
311
312 return result;
313 }
314
318 Str<T, N> operator+(const Str<T, N>& str) const
319 {
320 Str<T, N> result(size + str.size);
321
322 Util::Copy(result.data, data, Size(true));
323
324 Util::Copy(&result.data[size], str.data, str.Size(true));
325
326 result.data[size + str.size] = 0;
327
328 return result;
329 }
330
334 Str<T, N> operator+(const SInt_64 num) const
335 {
336 return operator+(FromNum(num));
337 }
338
342 Str<T, N> operator+(const UInt_64 num) const
343 {
344 return operator+(FromNum(num));
345 }
346
350 Str<T, N> operator+(const SInt_32 num) const
351 {
352 return operator+(FromNum(num));
353 }
354
358 Str<T, N> operator+(const UInt_32 num) const
359 {
360 return operator+(FromNum(num));
361 }
362
366 Str<T, N> operator+(const SInt_16 num) const
367 {
368 return operator+(FromNum(num));
369 }
370
374 Str<T, N> operator+(const UInt_16 num) const
375 {
376 return operator+(FromNum(num));
377 }
378
382 Str<T, N> operator+(const SInt_8 num) const
383 {
384 return operator+(FromNum(num));
385 }
386
390 Str<T, N> operator+(const UInt_8 num) const
391 {
392 return operator+(FromNum(num));
393 }
394
395 #ifdef EHS_OS_WINDOWS
399 Str<T, N> operator+(const DWORD num) const
400 {
401 return operator+(FromNum(num));
402 }
403
407 Str<T, N> operator+(const HRESULT num) const
408 {
409 return operator+(FromNum(num));
410 }
411 #endif
412
416 Str<T, N> operator+(const float num) const
417 {
418 return operator+(FromNum(num));
419 }
420
424 Str<T, N> operator+(const double num) const
425 {
426 return operator+(FromNum(num));
427 }
428
432 Str<T, N> operator+(const long double num) const
433 {
434 return operator+(FromNum(num));
435 }
436
440 bool operator==(T* str) const
441 {
442 if (size != Len(str))
443 return false;
444
445 return Util::Compare(data, str, Size(true));
446 }
447
451 bool operator==(const T* const str) const
452 {
453 if (size != Len(str))
454 return false;
455
456 return Util::Compare(data, str, Size(true));
457 }
458
462 bool operator==(const Str<T, N>& str) const
463 {
464 if (size != str.size)
465 return false;
466
467 return Util::Compare(data, str, Size(true));
468 }
469
473 bool operator!=(const T* const str) const
474 {
475 if (size != Len(str))
476 return true;
477
478 return !Util::Compare(data, str, Size(true));
479 }
480
484 bool operator!=(const Str<T, N>& str) const
485 {
486 if (size != str.size)
487 return true;
488
489 return !Util::Compare(data, str, Size(true));
490 }
491
493 operator T* () const
494 {
495 return data;
496 }
497
500 void Resize(const N newSize)
501 {
502 if (newSize == size)
503 return;
504
505 T* result = new T[newSize + 1];
506
507 if (newSize > size)
508 Util::Copy(result, data, Size(true));
509 else
510 Util::Copy(result, data, newSize * sizeof(T));
511
512 size = newSize;
513
514 delete[] data;
515
516 data = result;
517 data[size] = 0;
518 }
519
523 N Size(bool inBytes = false) const
524 {
525 if (inBytes)
526 return sizeof(T) * size;
527 else
528 return size;
529 }
530
533 {
534 size = Len(data);
535
536 T* result = new T[size + 1];
537 Util::Copy(result, data, Size(true));
538
539 delete[] data;
540
541 result[size] = 0;
542 data = result;
543 }
544
548 void Copy(const N dstOffset, const Str<T, N>& src)
549 {
550 if (dstOffset + src.size > size)
551 {
552 //Log_8 log(__FUNCSIG__, LogType::ERR, 0, "The parameters \"dstOffset\" (" + Str_8::FromNum(dstOffset) + ") + \"srcSize\" (" + Str_8::FromNum(src.Size()) + ") is greater than the referenced string object's size (" + Str_8::FromNum(size) + ").");
553 return;
554 }
555
556 Util::Copy(&data[dstOffset], src, src.Size(true));
557 }
558
562 void Copy(const N dstOffset, const T* const src)
563 {
564 N srcSize = Len(src);
565
566 if (dstOffset + srcSize > size)
567 {
568 //Log_8 log(__FUNCSIG__, LogType::ERR, 0, "The parameters \"dstOffset\" (" + Str_8::FromNum(dstOffset) + ") + \"srcSize\" (" + Str_8::FromNum(srcSize) + ") is greater than the referenced string object's size (" + Str_8::FromNum(size) + ").");
569 return;
570 }
571
572 Util::Copy(&data[dstOffset], src, srcSize * sizeof(T));
573 }
574
579 void Copy(const N dstOffset, const T* const src, const N srcSize)
580 {
581 if (dstOffset + srcSize > size)
582 {
583 //Log_8 log(__FUNCSIG__, LogType::ERR, 0, "The parameters \"dstOffset\" (" + Str_8::FromNum(dstOffset) + ") + \"srcSize\" (" + Str_8::FromNum(srcSize) + ") is greater than the referenced string object's size (" + Str_8::FromNum(size) + ").");
584 return;
585 }
586
587 Util::Copy(&data[dstOffset], src, srcSize * sizeof(T));
588 }
589
593 void Insert(const N index, const Str& value)
594 {
595 if (!value.size)
596 return;
597
598 N newSize = size + value.size;
599
600 T* result = new T[newSize + 1];
601
602 Util::Copy(result, data, index * sizeof(T));
603
604 Util::Copy(&result[index], value.data, value.Size(true));
605
606 Util::Copy(&result[index + value.size], &data[index], size - index);
607
608 result[newSize] = 0;
609
610 delete[] data;
611 data = result;
612 size = newSize;
613 }
614
618 void Insert(const N index, const T value)
619 {
620 N newSize = 0;
621 if (index > size - 1)
622 newSize = size + ((index + 1) - size);
623 else
624 newSize = size + 1;
625
626 T* result = new T[newSize + 1];
627
628 for (N i = 0; i < index; ++i)
629 result[i] = data[i];
630
631 result[index] = value;
632
633 for (N i = index; i < size; ++i)
634 result[i + 1] = data[i];
635
636 result[newSize] = 0;
637
638 delete[] data;
639 data = result;
640 size = newSize;
641 }
642
647 Str Remove(const N start, const N end)
648 {
649 if (!size || start >= size || end > size || end <= start)
650 return {};
651
652 Str popped(&data[start], end - start);
653
654 N newSize = size - popped.size;
655 T* result = new T[newSize + 1];
656
657 Util::Copy(result, data, start * sizeof(T));
658
659 Util::Copy(&result[start], &data[end], (size - end) * sizeof(T));
660
661 result[newSize] = 0;
662
663 delete[] data;
664 data = result;
665 size = newSize;
666
667 return popped;
668 }
669
673 T Remove(const N index)
674 {
675 T popped = {};
676
677 if (!size || index >= size)
678 return popped;
679
680 popped = data[index];
681
682 N newSize = size - 1;
683 T* result = new T[newSize];
684
685 for (N i = 0; i < index; ++i)
686 result[i] = data[i];
687
688 for (N i = index + 1; i < size; ++i)
689 result[i - 1] = data[i];
690
691 delete[] data;
692 data = result;
693 size = newSize;
694
695 return popped;
696 }
697
700 void Push(const Str<T, N> &value)
701 {
702 T* result = new T[size + value.size + 1];
703 Util::Copy(result, data, Size(true));
704 Util::Copy(&result[size], value, value.Size(true));
705
706 result[size + value.Size()] = 0;
707
708 delete[] data;
709
710 data = result;
711 size += value.size;
712 }
713
717 void Push(const T* const value, const N size)
718 {
719 T* result = new T[this->size + size + 1];
720 Util::Copy(result, data, Size(true));
721 Util::Copy(&result[this->size], value, size * sizeof(T));
722
723 result[this->size + size] = 0;
724
725 delete[] data;
726
727 data = result;
728 this->size += size;
729 }
730
733 void Push(const T* const value)
734 {
735 N inSize = Len(value);
736
737 T* result = new T[size + inSize + 1];
738 Util::Copy(result, data, Size(true));
739 Util::Copy(&result[size], value, inSize * sizeof(T));
740
741 result[size + inSize] = 0;
742
743 delete[] data;
744
745 data = result;
746 size += inSize;
747 }
748
751 void Push(const T value)
752 {
753 T* result = new T[size + 2];
754
755 Util::Copy(result, data, Size(true));
756
757 result[size] = value;
758 result[size + 1] = 0;
759
760 delete[] data;
761
762 data = result;
763 ++size;
764 }
765
768 T Pop()
769 {
770 T* result = new T[size--];
771
772 T value = data[size];
773
774 Util::Copy(result, data, Size(true));
775
776 result[size] = 0;
777
778 delete[] data;
779
780 data = result;
781
782 return value;
783 }
784
787 const Byte* ToBytes() const
788 {
789 return (Byte*)data;
790 }
791
795 {
796 return (Byte*)data;
797 }
798
800 void ToLower()
801 {
802 for (N i = 0; i < size; ++i)
803 if (data[i] > 64 && data[i] < 91)
804 data[i] += 32;
805 }
806
810 {
811 Str<T, N> result(size);
812
813 for (N i = 0; i < size; ++i)
814 if (data[i] > 64 && data[i] < 91)
815 result[i] = data[i] + 32;
816 else
817 result[i] = data[i];
818
819 return result;
820 }
821
823 void ToUpper()
824 {
825 for (N i = 0; i < size; ++i)
826 if (data[i] > 96 && data[i] < 123)
827 data[i] -= 32;
828 }
829
833 {
834 Str<T, N> result(size);
835
836 for (N i = 0; i < size; ++i)
837 if (data[i] > 96 && data[i] < 123)
838 result[i] = data[i] - 32;
839 else
840 result[i] = data[i];
841
842 return result;
843 }
844
846 void Reverse()
847 {
848 if (size <= 1 || !data)
849 return;
850
851 T* r = new T[size + 1];
852
853 for (N i = 0; i < size; ++i)
854 r[i] = data[size - 1 - i];
855
856 r[size] = 0;
857
858 delete[] data;
859
860 data = r;
861 }
862
866 {
867 if (size <= 1 || !data)
868 return *this;
869
870 Str<T, N> r(size);
871
872 for (N i = 0; i < size; ++i)
873 r[i] = data[size - 1 - i];
874
875 return r;
876 }
877
882 Str<T, N> Sub(const N index, const N size = 0) const
883 {
884 if (index >= this->size)
885 {
886 //Log_8 log(__FUNCSIG__, LogType::ERR, 0, "The given index parameter, \"" + Str<T, N>::FromNum(index) + "\" is greater than the string's size, \"" + Str<T, N>::FromNum(this->size) + "\".");
887
888 return Str<T, N>();
889 }
890
891 if (size)
892 {
893 if (size > this->size)
894 {
895 //Log_8 log(__FUNCSIG__, LogType::ERR, 1, "The given size parameter, \"" + Str<T, N>::FromNum(size) + "\" is greater than the string's size, \"" + Str<T, N>::FromNum(this->size) + "\", at the index, \"" + Str<T, N>::FromNum(index) + "\".");
896
897 return Str<T, N>();
898 }
899
900 Str<T, N> result(size);
901
902 Util::Copy(result, &data[index], result.Size(true));
903
904 return result;
905 }
906 else
907 {
908 Str<T, N> result(this->size - index);
909
910 Util::Copy(result, &data[index], result.Size(true));
911
912 return result;
913 }
914 }
915
920 Vector<Str<T, N>, N> Split(const Str<T, N>& ide, const N max = 0) const
921 {
922 Vector<Str<T, N>, N> result(0, 5);
923
924 N b = 0;
925
926 for (N i = 0, c = 0; i < size; ++i)
927 {
928 if (data[i] == ide[c])
929 {
930 if (++c == ide.Size())
931 {
932 N r = i - (c - 1) - b;
933 if (!r)
934 result.Push(Str<T, N>());
935 else
936 result.Push(Str<T, N>(&data[b], r));
937
938 b = i + 1;
939 c = 0;
940
941 if (max && result.Size() == max)
942 break;
943 }
944 }
945 else
946 {
947 c = 0;
948 }
949 }
950
951 if (b < size)
952 result.Push(Str<T, N>(&data[b], size - b));
953
954 return result;
955 }
956
960 Str<T, N> RemoveAll(const Str<T, N>& ide) const
961 {
962 Str<T, N> result(size);
963
964 for (N i = 0, b = 0, c = 0; i < size; ++i)
965 {
966 if (data[i] == ide[c])
967 {
968 if (++c == ide.Size())
969 c = 0;
970 }
971 else
972 {
973 if (c)
974 for (N d = c; d < 0; --d)
975 result[b++] = data[i - d];
976 else
977 result[b++] = data[i];
978
979 c = 0;
980 }
981 }
982
983 return result;
984 }
985
990 Str ReplaceAll(const Str& ide, const Str& replacer) const
991 {
992 Str<T, N> result;
993
994 for (N i = 0, b = 0; i < size; ++i)
995 {
996 if (data[i] == ide[b])
997 {
998 if (++b == ide.Size())
999 {
1000 result.Push(replacer);
1001 b = 0;
1002 }
1003 }
1004 else
1005 {
1006 result.Push(data[i]);
1007 }
1008 }
1009
1010 return result;
1011 }
1012
1019 bool Find(const Str<T, N> &ide, N* const index = nullptr, const SearchPattern pattern = SearchPattern::LEFT_RIGHT, const IndexResult result = IndexResult::BEGINNING) const
1020 {
1021 if (pattern == SearchPattern::LEFT_RIGHT)
1022 {
1023 for (N i = 0, c = 0; i < size; ++i)
1024 {
1025 if (data[i] == ide[c])
1026 {
1027 if (++c == ide.Size())
1028 {
1029 if (result == IndexResult::BEGINNING)
1030 {
1031 if (index)
1032 *index = i - (c - 1);
1033
1034 return true;
1035 }
1036 else
1037 {
1038 if (index)
1039 *index = i;
1040
1041 return true;
1042 }
1043 }
1044 }
1045 }
1046 }
1047 else if (pattern == SearchPattern::RIGHT_LEFT)
1048 {
1049 for (N i = size, c = ide.Size(); i > 0; --i)
1050 {
1051 if (data[i - 1] == ide[c - 1])
1052 {
1053 if (--c == 0)
1054 {
1055 if (result == IndexResult::BEGINNING)
1056 {
1057 if (index)
1058 *index = i - (ide.Size() - 1);
1059
1060 return true;
1061 }
1062 else
1063 {
1064 if (index)
1065 *index = i;
1066
1067 return true;
1068 }
1069 }
1070 }
1071 }
1072 }
1073
1074 return false;
1075 }
1076
1081 bool Contains(const Str<T, N>& ide, const SearchPattern pattern = SearchPattern::LEFT_RIGHT) const
1082 {
1083 if (pattern == SearchPattern::LEFT_RIGHT)
1084 {
1085 for (N i = 0, c = 0; i < size; ++i)
1086 {
1087 if (data[i] == ide[c])
1088 {
1089 if (++c == ide.Size())
1090 {
1091 return true;
1092 }
1093 }
1094 }
1095 }
1096 else if (pattern == SearchPattern::RIGHT_LEFT)
1097 {
1098 for (N i = size, c = ide.Size(); i > 0; --i)
1099 {
1100 if (data[i - 1] == ide[c - 1])
1101 {
1102 if (--c == 0)
1103 {
1104 return true;
1105 }
1106 }
1107 }
1108 }
1109
1110 return false;
1111 }
1112
1115 bool IsNum() const
1116 {
1117 if (!size)
1118 return false;
1119
1120 if ((data[0] < '0' || data[0] > '9') && data[0] != '-' && data[0] != '.')
1121 return false;
1122
1123 for (N i = 1; i < size; ++i)
1124 if ((data[i] < '0' || data[i] > '9') && data[i] != '.')
1125 return false;
1126
1127 return true;
1128 }
1129
1134 template<typename I = int>
1135 static Str NumToHex(const I num)
1136 {
1137 static const T hex[] = "0123456789ABCDEF";
1138
1139 Str result(sizeof(I) * 2);
1140
1141 for (UInt_8 i = 0; i < sizeof(I); ++i)
1142 {
1143 result[i * 2] = hex[((Byte*)&num)[i] / 16];
1144 result[i * 2 + 1] = hex[((Byte*)&num)[i] % 16];
1145 }
1146
1147 return result;
1148 }
1149
1154 template<typename I = int>
1155 static I HexToNum(const Str& in)
1156 {
1157 N offset = 0;
1158 bool neg = false;
1159
1160 if (in[offset] == 45)
1161 {
1162 neg = true;
1163 ++offset;
1164 }
1165 else if (in[offset] == 43)
1166 ++offset;
1167
1168 if (in[offset] == 48 && (in[offset + 1] == 88 || in[offset + 1] == 120))
1169 offset += 2;
1170
1171 N acc = 0;
1172
1173 for (N i = offset; i < in.Size(); ++i)
1174 {
1175 I value = 0;
1176
1177 if (in[i] > 47 && in[i] < 58)
1178 value = in[i] - 48;
1179 else if (in[i] > 64 && in[i] < 71)
1180 value = in[i] - 55;
1181 else if (in[i] > 96 && in[i] < 103)
1182 value = in[i] - 87;
1183
1184 if (value >= 16)
1185 return 0;
1186
1187 acc *= 16;
1188 acc += value;
1189 }
1190
1191 return neg ? -acc : acc;
1192 }
1193
1197 template<typename I = int>
1198 I HexToNum() const
1199 {
1200 N offset = 0;
1201 bool neg = false;
1202
1203 if (data[offset] == 45)
1204 {
1205 neg = true;
1206 ++offset;
1207 }
1208 else if (data[offset] == 43)
1209 ++offset;
1210
1211 if (data[offset] == 48 && (data[offset + 1] == 88 || data[offset + 1] == 120))
1212 offset += 2;
1213
1214 N acc = 0;
1215
1216 for (N i = offset; i < size; ++i)
1217 {
1218 I value = 0;
1219
1220 if (data[i] > 47 && data[i] < 58)
1221 value = data[i] - 48;
1222 else if (data[i] > 64 && data[i] < 71)
1223 value = data[i] - 55;
1224 else if (data[i] > 96 && data[i] < 103)
1225 value = data[i] - 87;
1226
1227 if (value >= 16)
1228 return 0;
1229
1230 acc *= 16;
1231 acc += value;
1232 }
1233
1234 return neg ? -acc : acc;
1235 }
1236
1241 template<typename I = N>
1242 I ToDecimal() const
1243 {
1244 I r = 0;
1245
1246 if (!size)
1247 return r;
1248
1249 for (N i = data[0] == '-' ? 1 : 0; i < size; ++i)
1250 r = r * 10 + data[i] - '0';
1251
1252 if (data[0] == '-')
1253 r *= -1;
1254
1255 return r;
1256 }
1257
1261 float ToFloat() const
1262 {
1263 Str<T, N> ide;
1264 ide.Push(46);
1265
1266 N decPoint = size;
1267 Find(ide, &decPoint);
1268
1269 float result = 0.0f;
1270 float fraction = 0.0f;
1271 float scale = 1.0f;
1272
1273 for (N i = 0; i < decPoint; ++i)
1274 result = result * 10.0f + data[i] - '0';
1275
1276 for (N i = decPoint + 1; i < size; ++i)
1277 {
1278 fraction = fraction * 10.0f + data[i] - '0';
1279 scale *= 10.0f;
1280 }
1281
1282 result += fraction / scale;
1283
1284 return result;
1285 }
1286
1290 double ToDouble() const
1291 {
1292 Str<T, N> ide;
1293 ide.Push(46);
1294
1295 N decPoint = size;
1296 Find(ide, &decPoint);
1297
1298 double result = 0.0f;
1299 double fraction = 0.0f;
1300 double scale = 1.0f;
1301
1302 for (N i = 0; i < decPoint; ++i)
1303 result = result * 10.0f + data[i] - '0';
1304
1305 for (N i = decPoint + 1; i < size; ++i)
1306 {
1307 fraction = fraction * 10.0f + data[i] - '0';
1308 scale *= 10.0f;
1309 }
1310
1311 result += fraction / scale;
1312
1313 return result;
1314 }
1315
1319 long double ToLDouble() const
1320 {
1321 Str<T, N> ide;
1322 ide.Push(46);
1323
1324 N decPoint = size;
1325 Find(ide, &decPoint);
1326
1327 long double result = 0.0f;
1328 long double fraction = 0.0f;
1329 long double scale = 1.0f;
1330
1331 for (N i = 0; i < decPoint; ++i)
1332 result = result * 10.0f + data[i] - '0';
1333
1334 for (N i = decPoint + 1; i < size; ++i)
1335 {
1336 fraction = fraction * 10.0f + data[i] - '0';
1337 scale *= 10.0f;
1338 }
1339
1340 result += fraction / scale;
1341
1342 return result;
1343 }
1344
1348 static Str<T, N> FromNum(const SInt_64 num)
1349 {
1350 if (num == 0)
1351 {
1352 Str<T, N> z(1);
1353 z[0] = 48;
1354 return z;
1355 }
1356
1357 Str<T, N> r(21);
1358
1359 SInt_64 nonNeg;
1360 if (num < 0)
1361 nonNeg = -num;
1362 else
1363 nonNeg = num;
1364
1365 N i = 0;
1366
1367 while (nonNeg != 0)
1368 {
1369 r[i++] = 48 + nonNeg % 10;
1370 nonNeg /= 10;
1371 }
1372
1373 if (num < 0)
1374 r[i++] = 45;
1375
1376 r.Resize(i);
1377
1378 return r.GetReverse();
1379 }
1380
1384 static Str<T, N> FromNum(const UInt_64 num)
1385 {
1386 if (num == 0)
1387 {
1388 Str<T, N> z(1);
1389 z[0] = 48;
1390 return z;
1391 }
1392
1393 Str<T, N> r(21);
1394
1395 UInt_64 nonNeg = num;
1396
1397 N i = 0;
1398
1399 while (nonNeg != 0)
1400 {
1401 r[i++] = 48 + nonNeg % 10;
1402 nonNeg /= 10;
1403 }
1404
1405 r.Resize(i);
1406
1407 return r.GetReverse();
1408 }
1409
1413 static Str<T, N> FromNum(const SInt_32 num)
1414 {
1415 if (num == 0)
1416 {
1417 Str<T, N> z(1);
1418 z[0] = 48;
1419 return z;
1420 }
1421
1422 Str<T, N> r(11);
1423
1424 SInt_32 nonNeg;
1425 if (num < 0)
1426 nonNeg = -num;
1427 else
1428 nonNeg = num;
1429
1430 N i = 0;
1431
1432 while (nonNeg != 0)
1433 {
1434 r[i++] = 48 + nonNeg % 10;
1435 nonNeg /= 10;
1436 }
1437
1438 if (num < 0)
1439 r[i++] = 45;
1440
1441 r.Resize(i);
1442
1443 return r.GetReverse();
1444 }
1445
1449 static Str<T, N> FromNum(const UInt_32 num)
1450 {
1451 if (num == 0)
1452 {
1453 Str<T, N> z(1);
1454 z[0] = 48;
1455 return z;
1456 }
1457
1458 Str<T, N> r(11);
1459
1460 UInt_32 nonNeg = num;
1461
1462 N i = 0;
1463
1464 while (nonNeg != 0)
1465 {
1466 r[i++] = 48 + nonNeg % 10;
1467 nonNeg /= 10;
1468 }
1469
1470 r.Resize(i);
1471
1472 return r.GetReverse();
1473 }
1474
1478 static Str<T, N> FromNum(const SInt_16 num)
1479 {
1480 if (num == 0)
1481 {
1482 Str<T, N> z(1);
1483 z[0] = 48;
1484 return z;
1485 }
1486
1487 Str<T, N> r(6);
1488
1489 SInt_16 nonNeg;
1490 if (num < 0)
1491 nonNeg = -num;
1492 else
1493 nonNeg = num;
1494
1495 N i = 0;
1496
1497 while (nonNeg != 0)
1498 {
1499 r[i++] = 48 + nonNeg % 10;
1500 nonNeg /= 10;
1501 }
1502
1503 if (num < 0)
1504 r[i++] = 45;
1505
1506 r.Resize(i);
1507
1508 return r.GetReverse();
1509 }
1510
1514 static Str<T, N> FromNum(const UInt_16 num)
1515 {
1516 if (num == 0)
1517 {
1518 Str<T, N> z(1);
1519 z[0] = 48;
1520 return z;
1521 }
1522
1523 Str<T, N> r(6);
1524
1525 UInt_16 nonNeg = num;
1526
1527 N i = 0;
1528
1529 while (nonNeg != 0)
1530 {
1531 r[i++] = 48 + nonNeg % 10;
1532 nonNeg /= 10;
1533 }
1534
1535 r.Resize(i);
1536
1537 return r.GetReverse();
1538 }
1539
1543 static Str<T, N> FromNum(const SInt_8 num)
1544 {
1545 if (num == 0)
1546 {
1547 Str<T, N> z(1);
1548 z[0] = 48;
1549 return z;
1550 }
1551
1552 Str<T, N> r(4);
1553
1554 SInt_8 nonNeg;
1555 if (num < 0)
1556 nonNeg = -num;
1557 else
1558 nonNeg = num;
1559
1560 N i = 0;
1561
1562 while (nonNeg != 0)
1563 {
1564 r[i++] = 48 + nonNeg % 10;
1565 nonNeg /= 10;
1566 }
1567
1568 if (num < 0)
1569 r[i++] = 45;
1570
1571 r.Resize(i);
1572
1573 return r.GetReverse();
1574 }
1575
1579 static Str<T, N> FromNum(const UInt_8 num)
1580 {
1581 if (num == 0)
1582 {
1583 Str<T, N> z(1);
1584 z[0] = 48;
1585 return z;
1586 }
1587
1588 Str<T, N> r(4);
1589
1590 UInt_8 nonNeg = num;
1591
1592 N i = 0;
1593
1594 while (nonNeg != 0)
1595 {
1596 r[i++] = 48 + nonNeg % 10;
1597 nonNeg /= 10;
1598 }
1599
1600 r.Resize(i);
1601
1602 return r.GetReverse();
1603 }
1604
1605 #ifdef EHS_OS_WINDOWS
1608 static Str<T, N> FromNum(const DWORD num)
1609 {
1610 if (num == 0)
1611 {
1612 Str<T, N> z(1);
1613 z[0] = 48;
1614 return z;
1615 }
1616
1617 Str<T, N> r(11);
1618
1619 DWORD nonNeg = num;
1620
1621 N i = 0;
1622
1623 while (nonNeg != 0)
1624 {
1625 r[i++] = 48 + nonNeg % 10;
1626 nonNeg /= 10;
1627 }
1628
1629 r.Resize(i);
1630
1631 return r.GetReverse();
1632 }
1633
1636 static Str<T, N> FromNum(const HRESULT num)
1637 {
1638 if (num == 0)
1639 {
1640 Str<T, N> z(1);
1641 z[0] = 48;
1642 return z;
1643 }
1644
1645 Str<T, N> r(11);
1646
1647 HRESULT nonNeg;
1648 if (num < 0)
1649 nonNeg = -num;
1650 else
1651 nonNeg = num;
1652
1653 N i = 0;
1654
1655 while (nonNeg != 0)
1656 {
1657 r[i++] = 48 + nonNeg % 10;
1658 nonNeg /= 10;
1659 }
1660
1661 if (num < 0)
1662 r[i++] = 45;
1663
1664 r.Resize(i);
1665
1666 return r.GetReverse();
1667 }
1668 #endif
1669
1674 static Str<T, N> FromNum(const float num, const UInt_8 maxDecimals = 5)
1675 {
1676 SInt_64 whole = (SInt_64)num;
1677
1678 Str<T, N> result;
1679 if (whole < 0)
1680 result.Push(45);
1681
1682 result += Str<T, N>::FromNum(whole);
1683
1684 UInt_64 power = 10;
1685 for (UInt_64 i = 0; i < (UInt_64)maxDecimals - 1; ++i)
1686 power *= 10;
1687
1688 SInt_64 fraction = (SInt_64)((num - (float)whole) * (float)power);
1689 if (!fraction)
1690 return result;
1691
1692 result.Push(46);
1693
1694 Str<T, N> fResult(maxDecimals);
1695 N i = 0;
1696
1697 while (fraction)
1698 {
1699 fResult[i++] = 48 + fraction % 10;
1700 fraction /= 10;
1701 }
1702
1703 while (i < maxDecimals)
1704 fResult[i++] = 48;
1705
1706 fResult.Reverse();
1707 result += fResult;
1708
1709 return result;
1710 }
1711
1716 static Str<T, N> FromNum(const double num, const UInt_8 maxDecimals = 5)
1717 {
1718 SInt_64 whole = (SInt_64)num;
1719
1720 Str<T, N> result;
1721 if (whole < 0)
1722 result.Push(45);
1723
1724 result += Str<T, N>::FromNum(whole);
1725
1726 UInt_64 power = 10;
1727 for (UInt_64 i = 0; i < (UInt_64)maxDecimals - 1; ++i)
1728 power *= 10;
1729
1730 SInt_64 fraction = (SInt_64)((num - (double)whole) * (double)power);
1731 if (!fraction)
1732 return result;
1733
1734 result.Push(46);
1735
1736 Str<T, N> fResult(maxDecimals);
1737 N i = 0;
1738
1739 while (fraction)
1740 {
1741 fResult[i++] = 48 + fraction % 10;
1742 fraction /= 10;
1743 }
1744
1745 while (i < maxDecimals)
1746 fResult[i++] = 48;
1747
1748 fResult.Reverse();
1749 result += fResult;
1750
1751 return result;
1752 }
1753
1758 static Str<T, N> FromNum(const long double num, const UInt_8 maxDecimals = 5)
1759 {
1760 SInt_64 whole = (SInt_64)num;
1761
1762 Str<T, N> result;
1763 if (whole < 0)
1764 result.Push(45);
1765
1766 result += Str<T, N>::FromNum(whole);
1767
1768 UInt_64 power = 10;
1769 for (UInt_64 i = 0; i < (UInt_64)maxDecimals - 1; ++i)
1770 power *= 10;
1771
1772 SInt_64 fraction = (SInt_64)((num - (long double)whole) * (long double)power);
1773 if (!fraction)
1774 return result;
1775
1776 result.Push(46);
1777
1778 Str<T, N> fResult(maxDecimals);
1779 N i = 0;
1780
1781 while (fraction)
1782 {
1783 fResult[i++] = 48 + fraction % 10;
1784 fraction /= 10;
1785 }
1786
1787 while (i < maxDecimals)
1788 fResult[i++] = 48;
1789
1790 fResult.Reverse();
1791 result += fResult;
1792
1793 return result;
1794 }
1795
1799 static UInt_32 Hash_32(const Str<T, N>& str)
1800 {
1801 if (!str.Size())
1802 return 0;
1803
1804 const Byte* const bytes = str.ToBytes();
1805
1806 UInt_32 hash = 2166136261ul;
1807
1808 for (N i = 0; i < str.Size(true); ++i)
1809 hash = (hash ^ bytes[i]) * 16777619;
1810
1811 return hash;
1812 }
1813
1817 {
1818 if (!size)
1819 return 0;
1820
1821 const Byte* const bytes = ToBytes();
1822
1823 UInt_32 hash = 2166136261ul;
1824
1825 for (N i = 0; i < Size(true); ++i)
1826 hash = (hash ^ bytes[i]) * 16777619;
1827
1828 return hash;
1829 }
1830
1834 static UInt_64 Hash_64(const Str<T, N>& str)
1835 {
1836 if (!str.Size())
1837 return 0;
1838
1839 const Byte* const bytes = str.ToBytes();
1840
1841 UInt_64 hash = 14695981039346656037ull;
1842
1843 for (N i = 0; i < str.Size(true); ++i)
1844 hash = (hash ^ bytes[i]) * 1099511628211;
1845
1846 return hash;
1847 }
1848
1851 UInt_64 Hash_64() const
1852 {
1853 if (!size)
1854 return 0;
1855
1856 const Byte* const bytes = ToBytes();
1857
1858 UInt_64 hash = 14695981039346656037ull;
1859
1860 for (N i = 0; i < Size(true); ++i)
1861 hash = (hash ^ bytes[i]) * 1099511628211;
1862
1863 return hash;
1864 }
1865
1869 static N Len(const T* const str)
1870 {
1871 if (!str)
1872 return 0;
1873
1874 N count = 0;
1875 while (str[count])
1876 ++count;
1877 return count;
1878 }
1879
1884 static bool Cmp(const T* const a, const T* const b)
1885 {
1886 N aSize = Len(a);
1887 N bSize = Len(b);
1888
1889 if (aSize != bSize)
1890 return false;
1891
1892 return Util::Compare(a, b, aSize);
1893 }
1894 };
1895
1896 template class EHS_LIB_IO Str<Char_32, UInt_64>;
1897 template class EHS_LIB_IO Str<Char_16, UInt_64>;
1898 template class EHS_LIB_IO Str<Char_8, UInt_64>;
1899
1903}
1904
1905template<typename T = ehs::Char_8, typename N = ehs::UInt_64>
1906bool operator==(const T* const first, const ehs::Str<T, N>& second)
1907{
1908 N inSize = ehs::Str<T, N>::Len(first);
1909 if (second.Size() != inSize)
1910 return false;
1911
1912 return ehs::Util::Compare(first, second, second.Size(true));
1913}
1914
1915template<typename T = ehs::Char_8, typename N = ehs::UInt_64>
1916bool operator!=(const T* const first, const ehs::Str<T, N>& second)
1917{
1918 N inSize = ehs::Str<T, N>::Len(first);
1919 if (second.Size() != inSize)
1920 return true;
1921
1922 return !ehs::Util::Compare(first, second, second.Size(true));
1923}
1924
1929template<typename T = ehs::Char_8, typename N = ehs::UInt_64>
1930ehs::Str<T, N> operator+(const T* const first, const ehs::Str<T, N>& second)
1931{
1932 N inSize = ehs::Str<T, N>::Len(first);
1933
1934 ehs::Str<T, N> result(inSize + second.Size());
1935
1936 ehs::Util::Copy(result, first, inSize * sizeof(T));
1937 ehs::Util::Copy(&result[inSize], &second[0], second.Size(true));
1938
1939 result[inSize + second.Size()] = 0;
1940
1941 return result;
1942}
bool operator!=(const T *const first, const ehs::Str< T, N > &second)
Definition: Str.h:1916
ehs::Str< T, N > operator+(const T *const first, const ehs::Str< T, N > &second)
Definition: Str.h:1930
bool operator==(const T *const first, const ehs::Str< T, N > &second)
Definition: Str.h:1906
Definition: Str.h:29
UInt_64 Hash_64() const
Definition: Str.h:1851
bool operator==(const T *const str) const
Definition: Str.h:451
void Copy(const N dstOffset, const Str< T, N > &src)
Definition: Str.h:548
Str< T, N > operator+(const UInt_16 num) const
Definition: Str.h:374
static Str< T, N > FromNum(const SInt_64 num)
Definition: Str.h:1348
Str< T, N > GetUpper() const
Definition: Str.h:832
Vector< Str< T, N >, N > Split(const Str< T, N > &ide, const N max=0) const
Definition: Str.h:920
static bool Cmp(const T *const a, const T *const b)
Definition: Str.h:1884
bool IsNum() const
Definition: Str.h:1115
void ToLower()
Converts all upper-case ASCII characters to lower-case.
Definition: Str.h:800
Str & operator=(const Str &str)
Definition: Str.h:116
void Insert(const N index, const Str &value)
Definition: Str.h:593
bool operator==(T *str) const
Definition: Str.h:440
Str< T, N > operator+(const Str< T, N > &str) const
Definition: Str.h:318
void Insert(const N index, const T value)
Definition: Str.h:618
Str< T, N > & operator+=(const long double num)
Definition: Str.h:292
void Push(const T *const value, const N size)
Definition: Str.h:717
bool operator!=(const T *const str) const
Definition: Str.h:473
static Str< T, N > FromNum(const UInt_64 num)
Definition: Str.h:1384
Str ReplaceAll(const Str &ide, const Str &replacer) const
Definition: Str.h:990
Str< T, N > operator+(const float num) const
Definition: Str.h:416
void Push(const T *const value)
Definition: Str.h:733
Str(const Str &str)
Definition: Str.h:90
Str< T, N > GetLower() const
Definition: Str.h:809
static UInt_64 Hash_64(const Str< T, N > &str)
Definition: Str.h:1834
Str< T, N > & operator+=(const UInt_16 num)
Definition: Str.h:234
Str< T, N > Sub(const N index, const N size=0) const
Definition: Str.h:882
Str< T, N > operator+(const SInt_16 num) const
Definition: Str.h:366
Str()
Default members initialization.
Definition: Str.h:42
Str< T, N > & operator+=(const UInt_32 num)
Definition: Str.h:218
static Str< T, N > FromNum(const UInt_8 num)
Definition: Str.h:1579
Str< T, N > & operator+=(const SInt_64 num)
Definition: Str.h:194
long double ToLDouble() const
Definition: Str.h:1319
void ToUpper()
Converts all lower-case ASCII characters to upper-case.
Definition: Str.h:823
static Str< T, N > FromNum(const UInt_16 num)
Definition: Str.h:1514
bool operator!=(const Str< T, N > &str) const
Definition: Str.h:484
void Push(const Str< T, N > &value)
Definition: Str.h:700
void Reverse()
Reverses the entire string object.
Definition: Str.h:846
static Str< T, N > FromNum(const SInt_32 num)
Definition: Str.h:1413
Str< T, N > RemoveAll(const Str< T, N > &ide) const
Definition: Str.h:960
static Str< T, N > FromNum(const SInt_16 num)
Definition: Str.h:1478
bool operator==(const Str< T, N > &str) const
Definition: Str.h:462
static Str< T, N > FromNum(const double num, const UInt_8 maxDecimals=5)
Definition: Str.h:1716
Str< T, N > & operator+=(const SInt_32 num)
Definition: Str.h:210
static I HexToNum(const Str &in)
Definition: Str.h:1155
static N Len(const T *const str)
Definition: Str.h:1869
I ToDecimal() const
Definition: Str.h:1242
Str(Str &&str) noexcept
A move constructor.
Definition: Str.h:81
Str< T, N > & operator+=(const double num)
Definition: Str.h:284
Str< T, N > & operator+=(const Str< T, N > &str)
Definition: Str.h:174
static Str< T, N > FromNum(const SInt_8 num)
Definition: Str.h:1543
Str< T, N > operator+(const UInt_8 num) const
Definition: Str.h:390
void Push(const T value)
Definition: Str.h:751
Str< T, N > & operator+=(const UInt_64 num)
Definition: Str.h:202
N Size(bool inBytes=false) const
Definition: Str.h:523
Str< T, N > operator+(const SInt_64 num) const
Definition: Str.h:334
Str(const T *const str)
Definition: Str.h:62
static Str< T, N > FromNum(const long double num, const UInt_8 maxDecimals=5)
Definition: Str.h:1758
Str< T, N > operator+(const UInt_64 num) const
Definition: Str.h:342
const Byte * ToBytes() const
Definition: Str.h:787
I HexToNum() const
Definition: Str.h:1198
Str< T, N > operator+(const double num) const
Definition: Str.h:424
Str< T, N > operator+(const SInt_8 num) const
Definition: Str.h:382
double ToDouble() const
Definition: Str.h:1290
Str< T, N > operator+(const SInt_32 num) const
Definition: Str.h:350
void Copy(const N dstOffset, const T *const src)
Definition: Str.h:562
Str< T, N > & operator+=(const T *const str)
Definition: Str.h:152
T Remove(const N index)
Definition: Str.h:673
Str< T, N > & operator+=(const SInt_8 num)
Definition: Str.h:242
void Resize(const N newSize)
Definition: Str.h:500
bool Find(const Str< T, N > &ide, N *const index=nullptr, const SearchPattern pattern=SearchPattern::LEFT_RIGHT, const IndexResult result=IndexResult::BEGINNING) const
Definition: Str.h:1019
Str< T, N > operator+(const UInt_32 num) const
Definition: Str.h:358
Str(const N size)
Definition: Str.h:74
bool Contains(const Str< T, N > &ide, const SearchPattern pattern=SearchPattern::LEFT_RIGHT) const
Definition: Str.h:1081
static Str NumToHex(const I num)
Definition: Str.h:1135
static UInt_32 Hash_32(const Str< T, N > &str)
Definition: Str.h:1799
Str< T, N > GetReverse()
Definition: Str.h:865
Str< T, N > & operator+=(const float num)
Definition: Str.h:276
Str & operator=(Str &&str) noexcept
Definition: Str.h:98
void ExactSize()
Finds the null terminator in the string and makes it the exact size if greater than.
Definition: Str.h:532
UInt_32 Hash_32() const
Definition: Str.h:1816
T Pop()
Definition: Str.h:768
static Str< T, N > FromNum(const float num, const UInt_8 maxDecimals=5)
Definition: Str.h:1674
~Str()
Frees any data created on the heap.
Definition: Str.h:36
static Str< T, N > FromNum(const UInt_32 num)
Definition: Str.h:1449
float ToFloat() const
Definition: Str.h:1261
Str< T, N > operator+(const T *const str) const
Definition: Str.h:300
Str< T, N > operator+(const long double num) const
Definition: Str.h:432
Str< T, N > & operator=(const T *const str)
Definition: Str.h:134
Str< T, N > & operator+=(const SInt_16 num)
Definition: Str.h:226
Byte * ToBytes()
Definition: Str.h:794
Str Remove(const N start, const N end)
Definition: Str.h:647
void Copy(const N dstOffset, const T *const src, const N srcSize)
Definition: Str.h:579
Str< T, N > & operator+=(const UInt_8 num)
Definition: Str.h:250
Str(const T *const str, const N size)
Definition: Str.h:50
static void Copy(void *out, const void *in, UInt_64 size)
Definition: Util.cpp:49
static bool Compare(const void *a, const void *b, UInt_64 size)
Definition: Util.cpp:5
Definition: Vector.h:18
void Push(const T *const value, const N size)
Definition: Vector.h:389
N Size() const
Definition: Vector.h:240
Definition: Anchor.h:6
IndexResult
Definition: Str.h:19
SearchPattern
Definition: Str.h:13
signed int SInt_32
Definition: Types.h:50
unsigned int UInt_32
Definition: Types.h:49
Str< Char_16, UInt_64 > Str_16
Definition: Str.h:1901
unsigned char UInt_8
Definition: Types.h:43
Str< Char_8, UInt_64 > Str_8
Definition: Str.h:1902
unsigned char Byte
Definition: Types.h:39
signed char SInt_8
Definition: Types.h:44
unsigned short UInt_16
Definition: Types.h:46
Str< Char_32, UInt_64 > Str_32
Definition: Str.h:1900
signed short SInt_16
Definition: Types.h:47