ArrayString.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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. template<int N>
  18. class Char32String;
  19. class CharString {
  20. protected:
  21. i32 length;
  22. i32 capacity;
  23. u32 hash;
  24. char* data;
  25. public:
  26. CharString(char* buffer, i32 bufferSize);
  27. CharString(const CharString&) = delete;
  28. CharString& operator=(const CharString&) = delete;
  29. check_return Error copyFrom(const CharString& s);
  30. bool operator==(const char* s) const;
  31. bool operator==(const CharString& other) const;
  32. bool operator!=(const char* s) const;
  33. bool operator!=(const CharString& other) const;
  34. char operator[](int index) const;
  35. int getLength() const;
  36. int getCapacity() const;
  37. check_return Error append(char c);
  38. check_return Error append(signed char c);
  39. check_return Error append(unsigned char c);
  40. check_return Error append(wchar_t c);
  41. check_return Error append(c32 c);
  42. check_return Error append(const char* s);
  43. check_return Error append(const c32* s);
  44. check_return Error append(const signed char* s);
  45. check_return Error append(const unsigned char* s);
  46. check_return Error append(bool b);
  47. check_return Error append(Error e);
  48. template<typename T>
  49. check_return Error append(const T& t) {
  50. if constexpr(requires { t.toString(*this); }) {
  51. return t.toString(*this);
  52. } else {
  53. char buffer[64];
  54. CORE_RETURN_ERROR(Core::toString(t, buffer, CORE_SIZE(buffer)));
  55. return append(static_cast<const char*>(buffer));
  56. }
  57. }
  58. check_return Error toString(CharString& s) const;
  59. template<int L>
  60. check_return Error toString(Char32String<L>& s) const {
  61. return s.append(static_cast<const char*>(data));
  62. }
  63. void clear();
  64. u32 hashCode() const;
  65. check_return Error print() const;
  66. check_return Error printLine() const;
  67. template<typename... Args>
  68. check_return Error format(CharString& s, Args&&... args) {
  69. Error e = formatBuffer(s, 0, Core::forward<Args>(args)...);
  70. if(e == Error::NONE) {
  71. return copyFrom(s);
  72. } else if(e == Error::CAPACITY_REACHED) {
  73. (void)copyFrom(s);
  74. }
  75. return e;
  76. }
  77. bool startsWidth(const CharString& other, int from = 0) const;
  78. int search(const CharString& other, int from = 0) const;
  79. bool contains(const CharString& other, int from = 0) const;
  80. int search(char u, int from = 0) const;
  81. bool contains(char u, int from = 0) const;
  82. check_return Error substring(CharString& s, int from, int to) const;
  83. check_return Error substring(CharString& s, int from = 0) const;
  84. check_return Error replace(CharString& s, const CharString& search,
  85. const CharString& replace);
  86. void replace(char search, char replace);
  87. operator const char*() const;
  88. private:
  89. void addToHash(c32 u);
  90. template<typename T, typename... Args>
  91. check_return Error formatBuffer(CharString& s, int index, const T& t,
  92. Args&&... args) {
  93. while(index < length) {
  94. char u = data[index++];
  95. if(u == '#') {
  96. if(index >= length ||
  97. (index < length && data[index] != '#')) {
  98. break;
  99. }
  100. index++;
  101. }
  102. CORE_RETURN_ERROR(s.append(u));
  103. }
  104. CORE_RETURN_ERROR(s.append(t));
  105. return formatBuffer(s, index, Core::forward<Args>(args)...);
  106. }
  107. check_return Error formatBuffer(CharString& s, int index);
  108. };
  109. template<int N>
  110. class Char32String final {
  111. int length;
  112. u32 hash;
  113. static_assert(N > 0, "size of array string must be positive");
  114. c32 data[static_cast<unsigned int>(N)];
  115. public:
  116. Char32String() : length(0), hash(0) {
  117. data[0] = '\0';
  118. }
  119. bool operator==(const c32* s) const {
  120. const c32* p = data;
  121. while(*s == *p && *s != '\0') {
  122. s++;
  123. p++;
  124. }
  125. return *s == *p;
  126. }
  127. template<int L>
  128. bool operator==(const Char32String<L>& other) const {
  129. if(length != other.getLength()) {
  130. return false;
  131. }
  132. for(int i = 0; i < length; i++) {
  133. if(data[i] != other[i]) {
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. bool operator!=(const c32* s) const {
  140. return !((*this) == s);
  141. }
  142. template<int L>
  143. bool operator!=(const Char32String<L>& other) const {
  144. return !((*this) == other);
  145. }
  146. c32 operator[](int index) const {
  147. return data[index];
  148. }
  149. int getLength() const {
  150. return length;
  151. }
  152. constexpr int getCapacity() const {
  153. return N - 1;
  154. }
  155. check_return Error append(char c) {
  156. return add(static_cast<c32>(c));
  157. }
  158. check_return Error append(signed char c) {
  159. return append(static_cast<char>(c));
  160. }
  161. check_return Error append(unsigned char c) {
  162. return append(static_cast<char>(c));
  163. }
  164. check_return Error append(wchar_t c) {
  165. return append(static_cast<c32>(c));
  166. }
  167. check_return Error append(c32 c) {
  168. if constexpr(IsSame<c32, char>) {
  169. char buffer[5];
  170. unicodeToChar(c, buffer);
  171. return append(static_cast<const char*>(buffer));
  172. } else {
  173. return add(c);
  174. }
  175. }
  176. check_return Error append(const char* s) {
  177. while(true) {
  178. c32 u = 0;
  179. CORE_RETURN_ERROR(readUnicode(u, s));
  180. if(u == 0) {
  181. return Error::NONE;
  182. }
  183. CORE_RETURN_ERROR(append(u));
  184. }
  185. }
  186. check_return Error append(const c32* s) {
  187. // stringLength as s could be some part of data
  188. for(int i = stringLength(s); i > 0; i--) {
  189. CORE_RETURN_ERROR(append(*(s++)));
  190. }
  191. return Error::NONE;
  192. }
  193. check_return Error append(const signed char* s) {
  194. return append(reinterpret_cast<const char*>(s));
  195. }
  196. check_return Error append(const unsigned char* s) {
  197. return append(reinterpret_cast<const char*>(s));
  198. }
  199. check_return Error append(signed short s) {
  200. return convertAppend(s);
  201. }
  202. check_return Error append(unsigned short s) {
  203. return convertAppend(s);
  204. }
  205. check_return Error append(signed int i) {
  206. return convertAppend(i);
  207. }
  208. check_return Error append(unsigned int i) {
  209. return convertAppend(i);
  210. }
  211. check_return Error append(signed long l) {
  212. return convertAppend(l);
  213. }
  214. check_return Error append(unsigned long l) {
  215. return convertAppend(l);
  216. }
  217. check_return Error append(signed long long ll) {
  218. return convertAppend(ll);
  219. }
  220. check_return Error append(unsigned long long ll) {
  221. return convertAppend(ll);
  222. }
  223. check_return Error append(float f) {
  224. return convertAppend(f);
  225. }
  226. check_return Error append(double d) {
  227. return convertAppend(d);
  228. }
  229. check_return Error append(long double ld) {
  230. return convertAppend(ld);
  231. }
  232. check_return Error append(bool b) {
  233. return b ? append("true") : append("false");
  234. }
  235. check_return Error append(Error e) {
  236. return append(getErrorName(e));
  237. }
  238. template<typename T>
  239. check_return Error append(const T& t) {
  240. return t.toString(*this);
  241. }
  242. check_return Error toString(CharString& s) const {
  243. int l = length; // length changes if &s == this
  244. for(int i = 0; i < l; i++) {
  245. CORE_RETURN_ERROR(s.append(data[i]));
  246. }
  247. return Error::NONE;
  248. }
  249. template<int L>
  250. check_return Error toString(Char32String<L>& s) const {
  251. int l = length; // length changes if &s == this
  252. for(int i = 0; i < l; i++) {
  253. CORE_RETURN_ERROR(s.append(data[i]));
  254. }
  255. return Error::NONE;
  256. }
  257. void clear() {
  258. length = 0;
  259. hash = 0;
  260. data[0] = '\0';
  261. }
  262. u32 hashCode() const {
  263. return hash;
  264. }
  265. check_return Error print() const {
  266. if constexpr(IsSame<c32, char>) {
  267. for(int i = 0; i < length; i++) {
  268. CORE_RETURN_ERROR(Core::putChar(data[i]));
  269. }
  270. return Error::NONE;
  271. } else {
  272. for(int i = 0; i < length; i++) {
  273. c32 c = data[i];
  274. if(c < (1 << 7)) {
  275. CORE_RETURN_ERROR(printChar(c, 0, 0x7F, 0x0));
  276. } else if(c < (1 << 11)) {
  277. CORE_RETURN_ERROR(printChar(c, 6, 0x1F, 0xC0));
  278. CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
  279. } else if(c < (1 << 16)) {
  280. CORE_RETURN_ERROR(printChar(c, 12, 0x0F, 0xE0));
  281. CORE_RETURN_ERROR(printChar(c, 6, 0x3F, 0x80));
  282. CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
  283. } else if(c < (1 << 21)) {
  284. CORE_RETURN_ERROR(printChar(c, 18, 0x07, 0xF0));
  285. CORE_RETURN_ERROR(printChar(c, 12, 0x3F, 0x80));
  286. CORE_RETURN_ERROR(printChar(c, 6, 0x3F, 0x80));
  287. CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
  288. }
  289. }
  290. return Error::NONE;
  291. }
  292. }
  293. check_return Error printLine() const {
  294. CORE_RETURN_ERROR(print());
  295. CORE_RETURN_ERROR(Core::putChar('\n'));
  296. return Error::NONE;
  297. }
  298. template<typename... Args>
  299. check_return Error format(Args&&... args) {
  300. Char32String s;
  301. Error e = formatBuffer(s, 0, Core::forward<Args>(args)...);
  302. if(e == Error::NONE || e == Error::CAPACITY_REACHED) {
  303. *this = s;
  304. }
  305. return e;
  306. }
  307. template<int L>
  308. bool startsWidth(const Char32String<L>& other, int from = 0) const {
  309. if(from > length - other.getLength()) {
  310. return false;
  311. }
  312. for(int i = 0; i < other.getLength(); i++) {
  313. if(data[from + i] != other[i]) {
  314. return false;
  315. }
  316. }
  317. return true;
  318. }
  319. template<int L>
  320. int search(const Char32String<L>& other, int from = 0) const {
  321. for(int i = from; i < length; i++) {
  322. if(startsWidth(other, i)) {
  323. return i;
  324. }
  325. }
  326. return -1;
  327. }
  328. template<int L>
  329. bool contains(const Char32String<L>& other, int from = 0) const {
  330. return search(other, from) >= 0;
  331. }
  332. int search(c32 u, int from = 0) const {
  333. for(int i = from; i < length; i++) {
  334. if(data[i] == u) {
  335. return i;
  336. }
  337. }
  338. return -1;
  339. }
  340. bool contains(c32 u, int from = 0) const {
  341. return search(u, from) >= 0;
  342. }
  343. Char32String substring(int from, int to) const {
  344. from = Math::max(from, 0);
  345. to = Math::min(to, length - 1);
  346. Char32String s;
  347. for(int i = from; i <= to; i++) {
  348. (void)s.append(data[i]);
  349. }
  350. return s;
  351. }
  352. Char32String substring(int from = 0) const {
  353. return substring(from, length - 1);
  354. }
  355. template<int L1, int L2>
  356. check_return Error replace(const Char32String<L1>& search,
  357. const Char32String<L2>& replace) {
  358. Char32String<N> s;
  359. int i = 0;
  360. while(i < length) {
  361. if(startsWidth(search, i)) {
  362. CORE_RETURN_ERROR(s.append(replace));
  363. i += search.getLength();
  364. } else {
  365. CORE_RETURN_ERROR(s.append(data[i]));
  366. i++;
  367. }
  368. }
  369. *this = s;
  370. return Error::NONE;
  371. }
  372. void replace(c32 search, c32 replace) {
  373. hash = 0;
  374. for(int i = 0; i < length; i++) {
  375. if(data[i] == search) {
  376. data[i] = replace;
  377. }
  378. addToHash(static_cast<c32>(data[i]));
  379. }
  380. }
  381. operator const c32*() const {
  382. return data;
  383. }
  384. private:
  385. Error add(c32 c) {
  386. if(length >= N - 1) {
  387. return Error::CAPACITY_REACHED;
  388. }
  389. data[length++] = c;
  390. data[length] = '\0';
  391. addToHash(static_cast<c32>(c));
  392. return Error::NONE;
  393. }
  394. template<unsigned int L>
  395. void unicodeToChar(c32 c, char (&buffer)[L]) {
  396. static_assert(L >= 5, "to small char buffer");
  397. buffer[0] = '\0';
  398. if(c < (1 << 7)) {
  399. buffer[0] = static_cast<char>(((c >> 0) & 0x7F) | 0x0);
  400. buffer[1] = '\0';
  401. } else if(c < (1 << 11)) {
  402. buffer[0] = static_cast<char>(((c >> 6) & 0x1F) | 0xC0);
  403. buffer[1] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
  404. buffer[2] = '\0';
  405. } else if(c < (1 << 16)) {
  406. buffer[0] = static_cast<char>(((c >> 12) & 0x0F) | 0xE0);
  407. buffer[1] = static_cast<char>(((c >> 6) & 0x3F) | 0x80);
  408. buffer[2] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
  409. buffer[3] = '\0';
  410. } else if(c < (1 << 21)) {
  411. buffer[0] = static_cast<char>(((c >> 18) & 0x07) | 0xF0);
  412. buffer[1] = static_cast<char>(((c >> 12) & 0x3F) | 0x80);
  413. buffer[2] = static_cast<char>(((c >> 6) & 0x3F) | 0x80);
  414. buffer[3] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
  415. buffer[4] = '\0';
  416. }
  417. }
  418. check_return static Error printChar(c32 u, u32 shift, u32 a, u32 o) {
  419. return Core::putChar(static_cast<int>(((u >> shift) & a) | o));
  420. }
  421. void addToHash(c32 u) {
  422. hash = static_cast<u32>(2120251889) * hash + static_cast<u32>(u);
  423. }
  424. template<typename T, typename... Args>
  425. check_return Error formatBuffer(Char32String& s, int index, const T& t,
  426. Args&&... args) {
  427. while(index < length) {
  428. c32 u = data[index++];
  429. if(u == '#') {
  430. if(index >= length ||
  431. (index < length && data[index] != '#')) {
  432. break;
  433. }
  434. index++;
  435. }
  436. CORE_RETURN_ERROR(s.append(u));
  437. }
  438. CORE_RETURN_ERROR(s.append(t));
  439. return formatBuffer(s, index, Core::forward<Args>(args)...);
  440. }
  441. check_return Error formatBuffer(Char32String& s, int index) {
  442. while(index < length) {
  443. CORE_RETURN_ERROR(s.append(data[index++]));
  444. }
  445. return Error::NONE;
  446. }
  447. template<typename T>
  448. check_return Error convertAppend(T t) {
  449. char buffer[64];
  450. CORE_RETURN_ERROR(Core::toString(t, buffer, CORE_SIZE(buffer)));
  451. return append(static_cast<const char*>(buffer));
  452. }
  453. };
  454. template<int N, typename C, typename B>
  455. class ArrayString final : public B {
  456. static_assert(N > 0, "size of array string must be positive");
  457. C data[static_cast<unsigned int>(N)];
  458. public:
  459. ArrayString() : B(data, N) {
  460. }
  461. ArrayString(const ArrayString& other) : B(data, N) {
  462. Core::memoryCopy(data, other.data, sizeof(data));
  463. B::length = other.length;
  464. B::hash = other.hash;
  465. }
  466. ArrayString& operator=(const ArrayString& other) {
  467. if(this != &other) {
  468. Core::memoryCopy(data, other.data, sizeof(data));
  469. B::length = other.length;
  470. B::hash = other.hash;
  471. }
  472. return *this;
  473. }
  474. template<typename... Args>
  475. check_return Error format(Args&&... args) {
  476. ArrayString s;
  477. return B::format(s, Core::forward<Args>(args)...);
  478. }
  479. check_return Error replace(const B& search, const B& replace) {
  480. ArrayString s;
  481. return B::replace(s, search, replace);
  482. }
  483. using B::replace;
  484. };
  485. template<typename String, typename Iterable>
  486. check_return Error toString(String& s, const Iterable& i) {
  487. CORE_RETURN_ERROR(s.append("["));
  488. auto current = i.begin();
  489. auto end = i.end();
  490. while(current != end) {
  491. CORE_RETURN_ERROR(s.append(*current));
  492. ++current;
  493. if(current != end) {
  494. CORE_RETURN_ERROR(s.append(", "));
  495. }
  496. }
  497. return s.append("]");
  498. }
  499. template<int N>
  500. using String8 = ArrayString<N, char, CharString>;
  501. template<int N>
  502. using String32 = Char32String<N>;
  503. }
  504. template<int N>
  505. bool operator==(const c32* cs, const Core::Char32String<N>& s) {
  506. return s == cs;
  507. }
  508. template<int N>
  509. bool operator!=(const c32* cs, const Core::Char32String<N>& s) {
  510. return s != cs;
  511. }
  512. inline bool operator==(const char* cs, const Core::CharString& s) {
  513. return s == cs;
  514. }
  515. inline bool operator!=(const char* cs, const Core::CharString& s) {
  516. return s != cs;
  517. }
  518. #endif