ArrayString.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #ifndef CORE_ARRAY_STRING_HPP
  2. #define CORE_ARRAY_STRING_HPP
  3. #include "core/math/Math.hpp"
  4. #include "core/utils/Check.hpp"
  5. #include "core/utils/Error.hpp"
  6. #include "core/utils/Meta.hpp"
  7. #include "core/utils/Types.hpp"
  8. #include "core/utils/Utility.hpp"
  9. namespace Core {
  10. template<typename T>
  11. constexpr int stringLength(const T* c) {
  12. const T* i = c + 1;
  13. while(*(c++) != '\0') {}
  14. return static_cast<int>(c - i);
  15. }
  16. Error readUnicode(c32& u, const char*& s);
  17. class Char32String;
  18. class CharString {
  19. protected:
  20. i32 length;
  21. i32 capacity;
  22. u32 hash;
  23. char* data;
  24. public:
  25. CharString(char* buffer, i32 bufferSize);
  26. CharString(const CharString&) = delete;
  27. CharString& operator=(const CharString&) = delete;
  28. check_return Error copyFrom(const CharString& s);
  29. bool operator==(const char* s) const;
  30. bool operator==(const CharString& other) const;
  31. bool operator!=(const char* s) const;
  32. bool operator!=(const CharString& other) const;
  33. char operator[](int index) const;
  34. int getLength() const;
  35. int getCapacity() const;
  36. check_return Error append(char c);
  37. check_return Error append(signed char c);
  38. check_return Error append(unsigned char c);
  39. check_return Error append(wchar_t c);
  40. check_return Error append(c32 c);
  41. check_return Error append(const char* s);
  42. check_return Error append(const c32* s);
  43. check_return Error append(const signed char* s);
  44. check_return Error append(const unsigned char* s);
  45. check_return Error append(bool b);
  46. check_return Error append(Error e);
  47. template<typename T>
  48. check_return Error append(const T& t) {
  49. if constexpr(requires { t.toString(*this); }) {
  50. return t.toString(*this);
  51. } else {
  52. char buffer[64];
  53. CORE_RETURN_ERROR(Core::toString(t, buffer, CORE_SIZE(buffer)));
  54. return append(static_cast<const char*>(buffer));
  55. }
  56. }
  57. check_return Error toString(CharString& s) const;
  58. check_return Error toString(Char32String& s) const;
  59. void clear();
  60. u32 hashCode() const;
  61. check_return Error print() const;
  62. check_return Error printLine() const;
  63. template<typename... Args>
  64. check_return Error format(CharString& s, Args&&... args) {
  65. Error e = formatBuffer(s, 0, Core::forward<Args>(args)...);
  66. if(e == Error::NONE) {
  67. return copyFrom(s);
  68. } else if(e == Error::CAPACITY_REACHED) {
  69. (void)copyFrom(s);
  70. }
  71. return e;
  72. }
  73. bool startsWidth(const CharString& other, int from = 0) const;
  74. int search(const CharString& other, int from = 0) const;
  75. bool contains(const CharString& other, int from = 0) const;
  76. int search(char u, int from = 0) const;
  77. bool contains(char u, int from = 0) const;
  78. check_return Error substring(CharString& s, int from, int to) const;
  79. check_return Error substring(CharString& s, int from = 0) const;
  80. check_return Error replace(CharString& s, const CharString& search,
  81. const CharString& replace);
  82. void replace(char search, char replace);
  83. operator const char*() const;
  84. private:
  85. void addToHash(c32 u);
  86. template<typename T, typename... Args>
  87. check_return Error formatBuffer(CharString& s, int index, const T& t,
  88. Args&&... args) {
  89. while(index < length) {
  90. char u = data[index++];
  91. if(u == '#') {
  92. if(index >= length ||
  93. (index < length && data[index] != '#')) {
  94. break;
  95. }
  96. index++;
  97. }
  98. CORE_RETURN_ERROR(s.append(u));
  99. }
  100. CORE_RETURN_ERROR(s.append(t));
  101. return formatBuffer(s, index, Core::forward<Args>(args)...);
  102. }
  103. check_return Error formatBuffer(CharString& s, int index);
  104. };
  105. class Char32String {
  106. protected:
  107. i32 length;
  108. i32 capacity;
  109. u32 hash;
  110. c32* data;
  111. public:
  112. Char32String(c32* buffer, i32 bufferSize);
  113. Char32String(const Char32String&) = delete;
  114. Char32String& operator=(const Char32String&) = delete;
  115. Error copyFrom(const Char32String& s);
  116. bool operator==(const c32* s) const;
  117. bool operator==(const Char32String& other) const;
  118. bool operator!=(const c32* s) const;
  119. bool operator!=(const Char32String& other) const;
  120. c32 operator[](int index) const;
  121. int getLength() const;
  122. int getCapacity() const;
  123. check_return Error append(char c);
  124. check_return Error append(signed char c);
  125. check_return Error append(unsigned char c);
  126. check_return Error append(wchar_t c);
  127. check_return Error append(c32 c);
  128. check_return Error append(const char* s);
  129. check_return Error append(const c32* s);
  130. check_return Error append(const signed char* s);
  131. check_return Error append(const unsigned char* s);
  132. check_return Error append(bool b);
  133. check_return Error append(Error e);
  134. template<typename T>
  135. check_return Error append(const T& t) {
  136. if constexpr(requires { t.toString(*this); }) {
  137. return t.toString(*this);
  138. } else {
  139. char buffer[64];
  140. CORE_RETURN_ERROR(Core::toString(t, buffer, CORE_SIZE(buffer)));
  141. return append(static_cast<const char*>(buffer));
  142. }
  143. }
  144. check_return Error toString(CharString& s) const;
  145. check_return Error toString(Char32String& s) const;
  146. void clear();
  147. u32 hashCode() const;
  148. check_return Error print() const;
  149. check_return Error printLine() const;
  150. template<typename... Args>
  151. check_return Error format(Char32String& s, Args&&... args) {
  152. Error e = formatBuffer(s, 0, Core::forward<Args>(args)...);
  153. if(e == Error::NONE) {
  154. return copyFrom(s);
  155. } else if(e == Error::CAPACITY_REACHED) {
  156. (void)copyFrom(s);
  157. }
  158. return e;
  159. }
  160. bool startsWidth(const Char32String& other, int from = 0) const;
  161. int search(const Char32String& other, int from = 0) const;
  162. bool contains(const Char32String& other, int from = 0) const;
  163. int search(c32 u, int from = 0) const;
  164. bool contains(c32 u, int from = 0) const;
  165. check_return Error substring(Char32String& s, int from, int to) const;
  166. check_return Error substring(Char32String& s, int from = 0) const;
  167. check_return Error replace(Char32String& s, const Char32String& search,
  168. const Char32String& replace);
  169. void replace(c32 search, c32 replace);
  170. operator const c32*() const;
  171. private:
  172. Error add(c32 c);
  173. void addToHash(c32 u);
  174. template<typename T, typename... Args>
  175. check_return Error formatBuffer(Char32String& s, int index, const T& t,
  176. Args&&... args) {
  177. while(index < length) {
  178. c32 u = data[index++];
  179. if(u == '#') {
  180. if(index >= length ||
  181. (index < length && data[index] != '#')) {
  182. break;
  183. }
  184. index++;
  185. }
  186. CORE_RETURN_ERROR(s.append(u));
  187. }
  188. CORE_RETURN_ERROR(s.append(t));
  189. return formatBuffer(s, index, Core::forward<Args>(args)...);
  190. }
  191. check_return Error formatBuffer(Char32String& s, int index);
  192. };
  193. template<int N, typename C, typename B>
  194. class ArrayString final : public B {
  195. static_assert(N > 0, "size of array string must be positive");
  196. C data[static_cast<unsigned int>(N)];
  197. public:
  198. ArrayString() : B(data, N) {
  199. }
  200. ArrayString(const ArrayString& other) : B(data, N) {
  201. Core::memoryCopy(data, other.data, sizeof(data));
  202. B::length = other.length;
  203. B::hash = other.hash;
  204. }
  205. ArrayString& operator=(const ArrayString& other) {
  206. if(this != &other) {
  207. Core::memoryCopy(data, other.data, sizeof(data));
  208. B::length = other.length;
  209. B::hash = other.hash;
  210. }
  211. return *this;
  212. }
  213. template<typename... Args>
  214. check_return Error format(Args&&... args) {
  215. ArrayString s;
  216. return B::format(s, Core::forward<Args>(args)...);
  217. }
  218. check_return Error replace(const B& search, const B& replace) {
  219. ArrayString s;
  220. return B::replace(s, search, replace);
  221. }
  222. using B::replace;
  223. };
  224. template<typename String, typename Iterable>
  225. check_return Error toString(String& s, const Iterable& i) {
  226. CORE_RETURN_ERROR(s.append("["));
  227. auto current = i.begin();
  228. auto end = i.end();
  229. while(current != end) {
  230. CORE_RETURN_ERROR(s.append(*current));
  231. ++current;
  232. if(current != end) {
  233. CORE_RETURN_ERROR(s.append(", "));
  234. }
  235. }
  236. return s.append("]");
  237. }
  238. template<int N>
  239. using String8 = ArrayString<N, char, CharString>;
  240. template<int N>
  241. using String32 = ArrayString<N, c32, Char32String>;
  242. }
  243. inline bool operator==(const c32* cs, const Core::Char32String& s) {
  244. return s == cs;
  245. }
  246. inline bool operator!=(const c32* cs, const Core::Char32String& s) {
  247. return s != cs;
  248. }
  249. inline bool operator==(const char* cs, const Core::CharString& s) {
  250. return s == cs;
  251. }
  252. inline bool operator!=(const char* cs, const Core::CharString& s) {
  253. return s != cs;
  254. }
  255. #endif