ArrayString.hpp 19 KB

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