#ifdef NALL_STRING_INTERNAL_HPP namespace nall { struct string_view; struct string; struct format; struct lstring; using rstring = const string_view&; using cstring = const string&; #define NALL_STRING_ALLOCATOR_ADAPTIVE //#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE //#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION //#define NALL_STRING_ALLOCATOR_VECTOR //cast.hpp template struct stringify; //format.hpp template inline auto print(P&&...) -> void; inline auto integer(intmax_t value, long precision = 0, char padchar = '0') -> string; inline auto decimal(uintmax_t value, long precision = 0, char padchar = '0') -> string; inline auto hex(uintmax_t value, long precision = 0, char padchar = '0') -> string; inline auto octal(uintmax_t value, long precision = 0, char padchar = '0') -> string; inline auto binary(uintmax_t value, long precision = 0, char padchar = '0') -> string; template inline auto pointer(const T* value, long precision = 0) -> string; inline auto pointer(uintptr_t value, long precision = 0) -> string; inline auto real(long double value) -> string; //hash.hpp inline auto crc16(rstring self) -> string; inline auto crc32(rstring self) -> string; inline auto sha256(rstring self) -> string; //match.hpp inline auto tokenize(const char* s, const char* p) -> bool; inline auto tokenize(lstring& list, const char* s, const char* p) -> bool; //path.hpp inline auto pathname(rstring self) -> string; inline auto filename(rstring self) -> string; inline auto dirname(rstring self) -> string; inline auto basename(rstring self) -> string; inline auto prefixname(rstring self) -> string; inline auto suffixname(rstring self) -> string; //platform.hpp inline auto activepath() -> string; inline auto realpath(rstring name) -> string; inline auto programpath() -> string; inline auto userpath() -> string; inline auto configpath() -> string; inline auto localpath() -> string; inline auto sharedpath() -> string; inline auto temppath() -> string; //utility.hpp inline auto slice(rstring self, signed offset = 0, signed length = -1) -> string; inline auto integer(char* result, intmax_t value) -> char*; inline auto decimal(char* result, uintmax_t value) -> char*; inline auto real(char* str, long double value) -> unsigned; struct string { using type = string; struct exception_out_of_bounds{}; protected: #if defined(NALL_STRING_ALLOCATOR_ADAPTIVE) enum : unsigned { SSO = 24 }; union { struct { //copy-on-write char* _data; unsigned* _refs; }; struct { //small-string-optimization char _text[SSO]; }; }; inline auto _allocate() -> void; inline auto _copy() -> void; inline auto _resize() -> void; #endif #if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE) char* _data; mutable unsigned* _refs; inline auto _allocate() -> char*; inline auto _copy() -> char*; #endif #if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION) enum : unsigned { SSO = 24 }; union { char* _data; char _text[SSO]; }; #endif #if defined(NALL_STRING_ALLOCATOR_VECTOR) char* _data; #endif unsigned _capacity; unsigned _size; public: inline string(); inline auto get() -> char*; inline auto data() const -> const char*; inline auto reset() -> type&; inline auto reserve(unsigned) -> type&; inline auto resize(unsigned) -> type&; inline auto operator=(const string&) -> type&; inline auto operator=(string&&) -> type&; template string(T&& s, P&&... p) : string() { append(forward(s), forward

(p)...); } ~string() { reset(); } explicit operator bool() const { return _size; } operator const uint8_t*() const { return (const uint8_t*)data(); } operator const char*() const { return (const char*)data(); } auto binary() const -> const uint8_t* { return (const uint8_t*)data(); } auto size() const -> unsigned { return _size; } auto capacity() const -> unsigned { return _capacity; } auto operator==(const string& s) const -> bool { return size() == s.size() && memory::compare(data(), s.data(), s.size()) == 0; } auto operator!=(const string& s) const -> bool { return size() != s.size() || memory::compare(data(), s.data(), s.size()) != 0; } auto operator==(const char* s) const -> bool { return strcmp(data(), s) == 0; } auto operator!=(const char* s) const -> bool { return strcmp(data(), s) != 0; } auto operator< (const char* s) const -> bool { return strcmp(data(), s) < 0; } auto operator<=(const char* s) const -> bool { return strcmp(data(), s) <= 0; } auto operator> (const char* s) const -> bool { return strcmp(data(), s) > 0; } auto operator>=(const char* s) const -> bool { return strcmp(data(), s) >= 0; } string(const string& source) : string() { operator=(source); } string(string&& source) : string() { operator=(move(source)); } auto begin() -> char* { return &get()[0]; } auto end() -> char* { return &get()[size()]; } auto begin() const -> const char* { return &data()[0]; } auto end() const -> const char* { return &data()[size()]; } //atoi.hpp inline auto integer() const -> intmax_t; inline auto decimal() const -> uintmax_t; inline auto real() const -> double; //core.hpp inline auto operator[](signed) const -> const char&; template inline auto assign(P&&...) -> type&; template inline auto append(const T&, P&&...) -> type&; template inline auto append(const nall::format&, P&&...) -> type&; inline auto append() -> type&; template inline auto _append(const stringify&) -> string&; inline auto empty() const -> bool; inline auto length() const -> unsigned; //datetime.hpp inline static auto date(time_t = 0) -> string; inline static auto time(time_t = 0) -> string; inline static auto datetime(time_t = 0) -> string; //find.hpp template inline auto _find(signed, rstring) const -> maybe; inline auto find(rstring source) const -> maybe; inline auto ifind(rstring source) const -> maybe; inline auto qfind(rstring source) const -> maybe; inline auto iqfind(rstring source) const -> maybe; inline auto findFrom(signed offset, rstring source) const -> maybe; inline auto ifindFrom(signed offset, rstring source) const -> maybe; //format.hpp inline auto format(const nall::format& params) -> type&; //compare.hpp template inline static auto _compare(const char*, unsigned, const char*, unsigned) -> signed; inline auto compare(rstring source) const -> signed; inline auto icompare(rstring source) const -> signed; inline auto equals(rstring source) const -> bool; inline auto iequals(rstring source) const -> bool; inline auto beginsWith(rstring source) const -> bool; inline auto ibeginsWith(rstring source) const -> bool; inline auto endsWith(rstring source) const -> bool; inline auto iendsWith(rstring source) const -> bool; //convert.hpp inline auto downcase() -> type&; inline auto upcase() -> type&; inline auto qdowncase() -> type&; inline auto qupcase() -> type&; inline auto transform(rstring from, rstring to) -> type&; //match.hpp inline auto match(rstring source) const -> bool; inline auto imatch(rstring source) const -> bool; //replace.hpp template inline auto _replace(rstring, rstring, long) -> type&; inline auto replace(rstring from, rstring to, long limit = LONG_MAX) -> type&; inline auto ireplace(rstring from, rstring to, long limit = LONG_MAX) -> type&; inline auto qreplace(rstring from, rstring to, long limit = LONG_MAX) -> type&; inline auto iqreplace(rstring from, rstring to, long limit = LONG_MAX) -> type&; //split.hpp inline auto split(rstring key, long limit = LONG_MAX) const -> lstring; inline auto isplit(rstring key, long limit = LONG_MAX) const -> lstring; inline auto qsplit(rstring key, long limit = LONG_MAX) const -> lstring; inline auto iqsplit(rstring key, long limit = LONG_MAX) const -> lstring; //trim.hpp inline auto trim(rstring lhs, rstring rhs, long limit = LONG_MAX) -> type&; inline auto ltrim(rstring lhs, long limit = LONG_MAX) -> type&; inline auto rtrim(rstring rhs, long limit = LONG_MAX) -> type&; inline auto itrim(rstring lhs, rstring rhs, long limit = LONG_MAX) -> type&; inline auto iltrim(rstring lhs, long limit = LONG_MAX) -> type&; inline auto irtrim(rstring rhs, long limit = LONG_MAX) -> type&; inline auto strip() -> type&; inline auto lstrip() -> type&; inline auto rstrip() -> type&; //utility.hpp inline static auto read(rstring filename) -> string; inline static auto repeat(rstring pattern, unsigned times) -> string; inline auto fill(char fill = ' ') -> type&; inline auto hash() const -> unsigned; inline auto remove(unsigned offset, unsigned length) -> type&; inline auto reverse() -> type&; inline auto size(signed length, char fill = ' ') -> type&; }; struct lstring : vector { using type = lstring; lstring(const lstring& source) { vector::operator=(source); } lstring(lstring& source) { vector::operator=(source); } lstring(lstring&& source) { vector::operator=(std::move(source)); } template lstring(P&&... p) { append(forward

(p)...); } //list.hpp inline auto operator==(const lstring&) const -> bool; inline auto operator!=(const lstring&) const -> bool; inline auto operator=(const lstring& source) -> type& { return vector::operator=(source), *this; } inline auto operator=(lstring& source) -> type& { return vector::operator=(source), *this; } inline auto operator=(lstring&& source) -> type& { return vector::operator=(std::move(source)), *this; } inline auto isort() -> type&; template inline auto append(const string&, P&&...) -> type&; inline auto append() -> type&; inline auto find(rstring source) const -> maybe; inline auto ifind(rstring source) const -> maybe; inline auto match(rstring pattern) const -> lstring; inline auto merge(rstring separator) const -> string; inline auto strip() -> type&; //split.hpp template inline auto _split(rstring, rstring, long) -> lstring&; }; struct format : vector { using type = format; template format(P&&... p) { reserve(sizeof...(p)); append(forward

(p)...); } template inline auto append(const T&, P&&... p) -> type&; inline auto append() -> type&; }; } #endif