string.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #pragma once
  2. #include <stdarg.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <algorithm>
  7. #include <initializer_list>
  8. #include <memory>
  9. #include <nall/platform.hpp>
  10. #include <nall/array-view.hpp>
  11. #include <nall/atoi.hpp>
  12. #include <nall/function.hpp>
  13. #include <nall/intrinsics.hpp>
  14. #include <nall/memory.hpp>
  15. #include <nall/primitives.hpp>
  16. #include <nall/shared-pointer.hpp>
  17. #include <nall/stdint.hpp>
  18. #include <nall/unique-pointer.hpp>
  19. #include <nall/utility.hpp>
  20. #include <nall/varint.hpp>
  21. #include <nall/vector.hpp>
  22. #include <nall/view.hpp>
  23. namespace nall {
  24. struct string;
  25. struct string_format;
  26. struct string_view {
  27. using type = string_view;
  28. //view.hpp
  29. string_view();
  30. string_view(const string_view& source);
  31. string_view(string_view&& source);
  32. string_view(const char* data);
  33. string_view(const char* data, uint size);
  34. string_view(const string& source);
  35. template<typename... P> string_view(P&&... p);
  36. ~string_view();
  37. auto operator=(const string_view& source) -> type&;
  38. auto operator=(string_view&& source) -> type&;
  39. explicit operator bool() const;
  40. operator const char*() const;
  41. auto data() const -> const char*;
  42. auto size() const -> uint;
  43. auto begin() const { return &_data[0]; }
  44. auto end() const { return &_data[size()]; }
  45. protected:
  46. string* _string;
  47. const char* _data;
  48. mutable int _size;
  49. };
  50. //adaptive (SSO + COW) is by far the best choice, the others exist solely to:
  51. //1) demonstrate the performance benefit of combining SSO + COW
  52. //2) rule out allocator bugs by trying different allocators when needed
  53. #define NALL_STRING_ALLOCATOR_ADAPTIVE
  54. //#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE
  55. //#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION
  56. //#define NALL_STRING_ALLOCATOR_VECTOR
  57. //cast.hpp
  58. template<typename T> struct stringify;
  59. //format.hpp
  60. template<typename... P> auto print(P&&...) -> void;
  61. template<typename... P> auto print(FILE*, P&&...) -> void;
  62. template<typename T> auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
  63. auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
  64. auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
  65. auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
  66. //match.hpp
  67. auto tokenize(const char* s, const char* p) -> bool;
  68. auto tokenize(vector<string>& list, const char* s, const char* p) -> bool;
  69. //utf8.hpp
  70. auto characters(string_view self, int offset = 0, int length = -1) -> uint;
  71. //utility.hpp
  72. auto slice(string_view self, int offset = 0, int length = -1) -> string;
  73. template<typename T> auto fromInteger(char* result, T value) -> char*;
  74. template<typename T> auto fromNatural(char* result, T value) -> char*;
  75. template<typename T> auto fromReal(char* str, T value) -> uint;
  76. struct string {
  77. using type = string;
  78. protected:
  79. #if defined(NALL_STRING_ALLOCATOR_ADAPTIVE)
  80. enum : uint { SSO = 24 };
  81. union {
  82. struct { //copy-on-write
  83. char* _data;
  84. uint* _refs;
  85. };
  86. struct { //small-string-optimization
  87. char _text[SSO];
  88. };
  89. };
  90. auto _allocate() -> void;
  91. auto _copy() -> void;
  92. auto _resize() -> void;
  93. #endif
  94. #if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
  95. char* _data;
  96. mutable uint* _refs;
  97. auto _allocate() -> char*;
  98. auto _copy() -> char*;
  99. #endif
  100. #if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
  101. enum : uint { SSO = 24 };
  102. union {
  103. char* _data;
  104. char _text[SSO];
  105. };
  106. #endif
  107. #if defined(NALL_STRING_ALLOCATOR_VECTOR)
  108. char* _data;
  109. #endif
  110. uint _capacity;
  111. uint _size;
  112. public:
  113. string();
  114. string(string& source) : string() { operator=(source); }
  115. string(const string& source) : string() { operator=(source); }
  116. string(string&& source) : string() { operator=(move(source)); }
  117. template<typename T = char> auto get() -> T*;
  118. template<typename T = char> auto data() const -> const T*;
  119. template<typename T = char> auto size() const -> uint { return _size / sizeof(T); }
  120. template<typename T = char> auto capacity() const -> uint { return _capacity / sizeof(T); }
  121. auto reset() -> type&;
  122. auto reserve(uint) -> type&;
  123. auto resize(uint) -> type&;
  124. auto operator=(const string&) -> type&;
  125. auto operator=(string&&) -> type&;
  126. template<typename T, typename... P> string(T&& s, P&&... p) : string() {
  127. append(forward<T>(s), forward<P>(p)...);
  128. }
  129. ~string() { reset(); }
  130. explicit operator bool() const { return _size; }
  131. operator const char*() const { return (const char*)data(); }
  132. operator array_span<char>() { return {(char*)get(), size()}; }
  133. operator array_view<char>() const { return {(const char*)data(), size()}; }
  134. operator array_span<uint8_t>() { return {(uint8_t*)get(), size()}; }
  135. operator array_view<uint8_t>() const { return {(const uint8_t*)data(), size()}; }
  136. auto operator==(const string& source) const -> bool {
  137. return size() == source.size() && memory::compare(data(), source.data(), size()) == 0;
  138. }
  139. auto operator!=(const string& source) const -> bool {
  140. return size() != source.size() || memory::compare(data(), source.data(), size()) != 0;
  141. }
  142. auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; }
  143. auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; }
  144. auto operator==(string_view source) const -> bool { return compare(source) == 0; }
  145. auto operator!=(string_view source) const -> bool { return compare(source) != 0; }
  146. auto operator< (string_view source) const -> bool { return compare(source) < 0; }
  147. auto operator<=(string_view source) const -> bool { return compare(source) <= 0; }
  148. auto operator> (string_view source) const -> bool { return compare(source) > 0; }
  149. auto operator>=(string_view source) const -> bool { return compare(source) >= 0; }
  150. auto begin() -> char* { return &get()[0]; }
  151. auto end() -> char* { return &get()[size()]; }
  152. auto begin() const -> const char* { return &data()[0]; }
  153. auto end() const -> const char* { return &data()[size()]; }
  154. //atoi.hpp
  155. auto boolean() const -> bool;
  156. auto integer() const -> intmax;
  157. auto natural() const -> uintmax;
  158. auto hex() const -> uintmax;
  159. auto real() const -> double;
  160. //core.hpp
  161. auto operator[](uint) const -> const char&;
  162. auto operator()(uint, char = 0) const -> char;
  163. template<typename... P> auto assign(P&&...) -> type&;
  164. template<typename T, typename... P> auto prepend(const T&, P&&...) -> type&;
  165. template<typename... P> auto prepend(const nall::string_format&, P&&...) -> type&;
  166. template<typename T> auto _prepend(const stringify<T>&) -> type&;
  167. template<typename T, typename... P> auto append(const T&, P&&...) -> type&;
  168. template<typename... P> auto append(const nall::string_format&, P&&...) -> type&;
  169. template<typename T> auto _append(const stringify<T>&) -> type&;
  170. auto length() const -> uint;
  171. //find.hpp
  172. auto contains(string_view characters) const -> maybe<uint>;
  173. template<bool, bool> auto _find(int, string_view) const -> maybe<uint>;
  174. auto find(string_view source) const -> maybe<uint>;
  175. auto ifind(string_view source) const -> maybe<uint>;
  176. auto qfind(string_view source) const -> maybe<uint>;
  177. auto iqfind(string_view source) const -> maybe<uint>;
  178. auto findFrom(int offset, string_view source) const -> maybe<uint>;
  179. auto ifindFrom(int offset, string_view source) const -> maybe<uint>;
  180. auto findNext(int offset, string_view source) const -> maybe<uint>;
  181. auto ifindNext(int offset, string_view source) const -> maybe<uint>;
  182. auto findPrevious(int offset, string_view source) const -> maybe<uint>;
  183. auto ifindPrevious(int offset, string_view source) const -> maybe<uint>;
  184. //format.hpp
  185. auto format(const nall::string_format& params) -> type&;
  186. //compare.hpp
  187. template<bool> static auto _compare(const char*, uint, const char*, uint) -> int;
  188. static auto compare(string_view, string_view) -> int;
  189. static auto icompare(string_view, string_view) -> int;
  190. auto compare(string_view source) const -> int;
  191. auto icompare(string_view source) const -> int;
  192. auto equals(string_view source) const -> bool;
  193. auto iequals(string_view source) const -> bool;
  194. auto beginsWith(string_view source) const -> bool;
  195. auto ibeginsWith(string_view source) const -> bool;
  196. auto endsWith(string_view source) const -> bool;
  197. auto iendsWith(string_view source) const -> bool;
  198. //convert.hpp
  199. auto downcase() -> type&;
  200. auto upcase() -> type&;
  201. auto qdowncase() -> type&;
  202. auto qupcase() -> type&;
  203. auto transform(string_view from, string_view to) -> type&;
  204. //match.hpp
  205. auto match(string_view source) const -> bool;
  206. auto imatch(string_view source) const -> bool;
  207. //replace.hpp
  208. template<bool, bool> auto _replace(string_view, string_view, long) -> type&;
  209. auto replace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  210. auto ireplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  211. auto qreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  212. auto iqreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  213. //split.hpp
  214. auto split(string_view key, long limit = LONG_MAX) const -> vector<string>;
  215. auto isplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  216. auto qsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  217. auto iqsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  218. //trim.hpp
  219. auto trim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
  220. auto trimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
  221. auto trimRight(string_view rhs, long limit = LONG_MAX) -> type&;
  222. auto itrim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
  223. auto itrimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
  224. auto itrimRight(string_view rhs, long limit = LONG_MAX) -> type&;
  225. auto strip() -> type&;
  226. auto stripLeft() -> type&;
  227. auto stripRight() -> type&;
  228. //utf8.hpp
  229. auto characters(int offset = 0, int length = -1) const -> uint;
  230. //utility.hpp
  231. static auto read(string_view filename) -> string;
  232. static auto repeat(string_view pattern, uint times) -> string;
  233. auto fill(char fill = ' ') -> type&;
  234. auto hash() const -> uint;
  235. auto remove(uint offset, uint length) -> type&;
  236. auto reverse() -> type&;
  237. auto size(int length, char fill = ' ') -> type&;
  238. auto slice(int offset = 0, int length = -1) const -> string;
  239. };
  240. template<> struct vector<string> : vector_base<string> {
  241. using type = vector<string>;
  242. using vector_base<string>::vector_base;
  243. vector(const vector& source) { vector_base::operator=(source); }
  244. vector(vector& source) { vector_base::operator=(source); }
  245. vector(vector&& source) { vector_base::operator=(move(source)); }
  246. template<typename... P> vector(P&&... p) { append(forward<P>(p)...); }
  247. auto operator=(const vector& source) -> type& { return vector_base::operator=(source), *this; }
  248. auto operator=(vector& source) -> type& { return vector_base::operator=(source), *this; }
  249. auto operator=(vector&& source) -> type& { return vector_base::operator=(move(source)), *this; }
  250. //vector.hpp
  251. template<typename... P> auto append(const string&, P&&...) -> type&;
  252. auto append() -> type&;
  253. auto isort() -> type&;
  254. auto find(string_view source) const -> maybe<uint>;
  255. auto ifind(string_view source) const -> maybe<uint>;
  256. auto match(string_view pattern) const -> vector<string>;
  257. auto merge(string_view separator) const -> string;
  258. auto strip() -> type&;
  259. //split.hpp
  260. template<bool, bool> auto _split(string_view, string_view, long) -> type&;
  261. };
  262. struct string_format : vector<string> {
  263. using type = string_format;
  264. template<typename... P> string_format(P&&... p) { reserve(sizeof...(p)); append(forward<P>(p)...); }
  265. template<typename T, typename... P> auto append(const T&, P&&... p) -> type&;
  266. auto append() -> type&;
  267. };
  268. inline auto operator"" _s(const char* value, std::size_t) -> string { return {value}; }
  269. }
  270. #include <nall/string/view.hpp>
  271. #include <nall/string/pascal.hpp>
  272. #include <nall/string/atoi.hpp>
  273. #include <nall/string/cast.hpp>
  274. #include <nall/string/compare.hpp>
  275. #include <nall/string/convert.hpp>
  276. #include <nall/string/core.hpp>
  277. #include <nall/string/find.hpp>
  278. #include <nall/string/format.hpp>
  279. #include <nall/string/match.hpp>
  280. #include <nall/string/replace.hpp>
  281. #include <nall/string/split.hpp>
  282. #include <nall/string/trim.hpp>
  283. #include <nall/string/utf8.hpp>
  284. #include <nall/string/utility.hpp>
  285. #include <nall/string/vector.hpp>
  286. #include <nall/string/eval/node.hpp>
  287. #include <nall/string/eval/literal.hpp>
  288. #include <nall/string/eval/parser.hpp>
  289. #include <nall/string/eval/evaluator.hpp>
  290. #include <nall/string/markup/node.hpp>
  291. #include <nall/string/markup/find.hpp>
  292. #include <nall/string/markup/bml.hpp>
  293. #include <nall/string/markup/xml.hpp>
  294. #include <nall/string/transform/cml.hpp>
  295. #include <nall/string/transform/dml.hpp>