string.hpp 14 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. inline string_view();
  30. inline string_view(const string_view& source);
  31. inline string_view(string_view&& source);
  32. inline string_view(const char* data);
  33. inline string_view(const char* data, uint size);
  34. inline string_view(const string& source);
  35. template<typename... P> inline string_view(P&&... p);
  36. inline ~string_view();
  37. inline auto operator=(const string_view& source) -> type&;
  38. inline auto operator=(string_view&& source) -> type&;
  39. inline explicit operator bool() const;
  40. inline operator const char*() const;
  41. inline auto data() const -> const char*;
  42. inline auto size() const -> uint;
  43. inline auto begin() const { return &_data[0]; }
  44. inline 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> inline auto print(P&&...) -> void;
  61. template<typename... P> inline auto print(FILE*, P&&...) -> void;
  62. template<typename T> inline auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
  63. inline auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
  64. inline auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
  65. inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
  66. //match.hpp
  67. inline auto tokenize(const char* s, const char* p) -> bool;
  68. inline auto tokenize(vector<string>& list, const char* s, const char* p) -> bool;
  69. //utf8.hpp
  70. inline auto characters(string_view self, int offset = 0, int length = -1) -> uint;
  71. //utility.hpp
  72. inline auto slice(string_view self, int offset = 0, int length = -1) -> string;
  73. template<typename T> inline auto fromInteger(char* result, T value) -> char*;
  74. template<typename T> inline auto fromNatural(char* result, T value) -> char*;
  75. template<typename T> inline 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. inline auto _allocate() -> void;
  91. inline auto _copy() -> void;
  92. inline auto _resize() -> void;
  93. #endif
  94. #if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
  95. char* _data;
  96. mutable uint* _refs;
  97. inline auto _allocate() -> char*;
  98. inline 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. inline string();
  114. inline string(string& source) : string() { operator=(source); }
  115. inline string(const string& source) : string() { operator=(source); }
  116. inline string(string&& source) : string() { operator=(move(source)); }
  117. template<typename T = char> inline auto get() -> T*;
  118. template<typename T = char> inline 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. inline auto reset() -> type&;
  122. inline auto reserve(uint) -> type&;
  123. inline auto resize(uint) -> type&;
  124. inline auto operator=(const string&) -> type&;
  125. inline 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. inline auto boolean() const -> bool;
  156. inline auto integer() const -> intmax;
  157. inline auto natural() const -> uintmax;
  158. inline auto hex() const -> uintmax;
  159. inline auto real() const -> double;
  160. //core.hpp
  161. inline auto operator[](uint) const -> const char&;
  162. inline auto operator()(uint, char = 0) const -> char;
  163. template<typename... P> inline auto assign(P&&...) -> type&;
  164. template<typename T, typename... P> inline auto prepend(const T&, P&&...) -> type&;
  165. template<typename... P> inline auto prepend(const nall::string_format&, P&&...) -> type&;
  166. template<typename T> inline auto _prepend(const stringify<T>&) -> type&;
  167. template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
  168. template<typename... P> inline auto append(const nall::string_format&, P&&...) -> type&;
  169. template<typename T> inline auto _append(const stringify<T>&) -> type&;
  170. inline auto length() const -> uint;
  171. //find.hpp
  172. inline auto contains(string_view characters) const -> maybe<uint>;
  173. template<bool, bool> inline auto _find(int, string_view) const -> maybe<uint>;
  174. inline auto find(string_view source) const -> maybe<uint>;
  175. inline auto ifind(string_view source) const -> maybe<uint>;
  176. inline auto qfind(string_view source) const -> maybe<uint>;
  177. inline auto iqfind(string_view source) const -> maybe<uint>;
  178. inline auto findFrom(int offset, string_view source) const -> maybe<uint>;
  179. inline auto ifindFrom(int offset, string_view source) const -> maybe<uint>;
  180. inline auto findNext(int offset, string_view source) const -> maybe<uint>;
  181. inline auto ifindNext(int offset, string_view source) const -> maybe<uint>;
  182. inline auto findPrevious(int offset, string_view source) const -> maybe<uint>;
  183. inline auto ifindPrevious(int offset, string_view source) const -> maybe<uint>;
  184. //format.hpp
  185. inline auto format(const nall::string_format& params) -> type&;
  186. //compare.hpp
  187. template<bool> inline static auto _compare(const char*, uint, const char*, uint) -> int;
  188. inline static auto compare(string_view, string_view) -> int;
  189. inline static auto icompare(string_view, string_view) -> int;
  190. inline auto compare(string_view source) const -> int;
  191. inline auto icompare(string_view source) const -> int;
  192. inline auto equals(string_view source) const -> bool;
  193. inline auto iequals(string_view source) const -> bool;
  194. inline auto beginsWith(string_view source) const -> bool;
  195. inline auto ibeginsWith(string_view source) const -> bool;
  196. inline auto endsWith(string_view source) const -> bool;
  197. inline auto iendsWith(string_view source) const -> bool;
  198. //convert.hpp
  199. inline auto downcase() -> type&;
  200. inline auto upcase() -> type&;
  201. inline auto qdowncase() -> type&;
  202. inline auto qupcase() -> type&;
  203. inline auto transform(string_view from, string_view to) -> type&;
  204. //match.hpp
  205. inline auto match(string_view source) const -> bool;
  206. inline auto imatch(string_view source) const -> bool;
  207. //replace.hpp
  208. template<bool, bool> inline auto _replace(string_view, string_view, long) -> type&;
  209. inline auto replace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  210. inline auto ireplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  211. inline auto qreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  212. inline auto iqreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
  213. //split.hpp
  214. inline auto split(string_view key, long limit = LONG_MAX) const -> vector<string>;
  215. inline auto isplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  216. inline auto qsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  217. inline auto iqsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
  218. //trim.hpp
  219. inline auto trim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
  220. inline auto trimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
  221. inline auto trimRight(string_view rhs, long limit = LONG_MAX) -> type&;
  222. inline auto itrim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
  223. inline auto itrimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
  224. inline auto itrimRight(string_view rhs, long limit = LONG_MAX) -> type&;
  225. inline auto strip() -> type&;
  226. inline auto stripLeft() -> type&;
  227. inline auto stripRight() -> type&;
  228. //utf8.hpp
  229. inline auto characters(int offset = 0, int length = -1) const -> uint;
  230. //utility.hpp
  231. inline static auto read(string_view filename) -> string;
  232. inline static auto repeat(string_view pattern, uint times) -> string;
  233. inline auto fill(char fill = ' ') -> type&;
  234. inline auto hash() const -> uint;
  235. inline auto remove(uint offset, uint length) -> type&;
  236. inline auto reverse() -> type&;
  237. inline auto size(int length, char fill = ' ') -> type&;
  238. inline 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. inline auto operator=(const vector& source) -> type& { return vector_base::operator=(source), *this; }
  248. inline auto operator=(vector& source) -> type& { return vector_base::operator=(source), *this; }
  249. inline auto operator=(vector&& source) -> type& { return vector_base::operator=(move(source)), *this; }
  250. //vector.hpp
  251. template<typename... P> inline auto append(const string&, P&&...) -> type&;
  252. inline auto append() -> type&;
  253. inline auto isort() -> type&;
  254. inline auto find(string_view source) const -> maybe<uint>;
  255. inline auto ifind(string_view source) const -> maybe<uint>;
  256. inline auto match(string_view pattern) const -> vector<string>;
  257. inline auto merge(string_view separator) const -> string;
  258. inline auto strip() -> type&;
  259. //split.hpp
  260. template<bool, bool> inline 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> inline auto append(const T&, P&&... p) -> type&;
  266. inline 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>