1#ifndef GIMBAL_STRING_HPP
2#define GIMBAL_STRING_HPP
4#include <gimbal/strings/gimbal_string_buffer.h>
5#include <gimbal/containers/gimbal_array_list.hpp>
7#include <unordered_set>
15template<
typename T,
typename SFINAE>
17 template<
typename F=T>
18 static F&& stringify(F&& value) {
return std::forward<F>(value); }
23concept string_base = std::is_base_of_v<gimbal::tags::StringBase, T>;
30template<
typename CRTP>
43 decltype(
auto) str_(
void)
const {
44 return static_cast<
const CRTP*>(
this)->getString_();
47 decltype(
auto) str_(
void) {
48 return static_cast<CRTP*>(
this)->getString_();
53 operator
const GblStringBuffer*()
const {
return str_(); }
56 const char& getElement_(size_t index)
const {
57 return getCString()[index];
60 char& getElement_(size_t index) {
61 return getCString()[index];
64 void setElement_(size_t index,
char value) {
65 const_cast<
char*>(getCString())[index] = value;
68 size_t getElementCount_(
void)
const {
74 Size getStackBytes(
void)
const {
75 Size size = GblStringBuffer_stackBytes(str_());
79 constexpr Size getLength(
void)
const {
80 return GblStringBuffer_length(str_());
83 constexpr Size getCapacity(
void)
const {
84 return GblStringBuffer_capacity(str_());
87 Context* getContext(
void)
const {
88 GblContext* pCtx = GblStringBuffer_context(str_());
89 return pCtx ==
nullptr?
nullptr : Context::fromGblObj(pCtx);
92 constexpr bool isEmpty(
void)
const {
93 GblBool empty = GblStringBuffer_empty(str_());
97 constexpr bool isStack(
void)
const {
98 GblBool stack = GblStringBuffer_stack(str_());
104 constexpr bool isHeap(
void)
const {
108 const char* getCString(
void)
const {
109 const char* pCStr = GblStringBuffer_cString(str_());
113 char* getCString(
void) {
114 const char* pStr = GblStringBuffer_cString(str_());
115 return const_cast<
char*>(pStr);
118 std::string toStdString(
void)
const {
119 return std::string(getCString());
122 constexpr std::string_view toStringView(
void)
const {
124 std::string_view(getCString(), getLength()) : std::string_view();
126 friend constexpr bool operator==(
const Derived& lhs,
const char* pRhs)
noexcept {
127 return (lhs.toStringView() == std::string_view(pRhs));
166class StringView
final:
public StringViewBase<StringView> {
168 const GblStringBuffer* pGblStr_ =
nullptr;
170 StringView(
void) =
default;
172 StringView(
const GblStringBuffer& gblStr):
175 StringView(
const gimbal::
String& string);
177 StringView(
const GblStringBuffer* pGblStringBuffer):
178 pGblStr_(pGblStringBuffer) {}
180 const GblStringBuffer* getString_(
void)
const {
return pGblStr_; }
181 bool isValid(
void)
const {
return pGblStr_; }
185 public GblStringBuffer,
191 return static_cast<
const GblStringBuffer*>(
this);
195 return static_cast<GblStringBuffer*>(
this);
201 String(std::nullptr_t, Size size=
sizeof(
String)):
202 String(
static_cast<Context*>(
nullptr), size) {}
204 String(Context* pCtx=
nullptr, Size size=
sizeof(
String)):
205 String(std::string_view{}, pCtx, size) {}
208 String(
const std::string& stdString, Context* pCtx=
nullptr, Size size=
sizeof(
String)):
209 String(std::string_view{stdString.c_str()}, pCtx, size) {}
216 String(
const char* pCStr, Context* pCtx=
nullptr, Size size=
sizeof(
String)):
217 String(pCStr? std::string_view{pCStr} : std::string_view{}, pCtx, size) {}
219 String(
const std::string_view& stringView, Context* pCtx=
nullptr, Size size=
sizeof(
String)) {
220 Exception::checkThrow(GblStringBuffer_construct(
this,
221 GBL_STRING_VIEW(stringView.data(), stringView.length()),
227 String(
const String& rhs, Context* pCtx=
nullptr, Size size=
sizeof(
String)):
228 String(StringView(rhs), pCtx, size) {}
230 String(StringView other, Context* pCtx=
nullptr, Size size=
sizeof(
String)):
231 String(other.toStringView(), pCtx? pCtx : other.getContext(), size) {}
234 String(
String&& rhs, Context* pCtx=
nullptr, Size size=
sizeof(
String)):
235 String(
static_cast<GblStringBuffer&&>(rhs), pCtx, size) {}
244 Exception::checkThrow(GblStringBuffer_destruct(
this));
247 static std::pair<
char*, Size> take(GblStringBuffer* pGblStr) {
248 char* pCStr =
nullptr;
250 Exception::checkThrow(GblStringBuffer_release(pGblStr, &pCStr, &capacity));
251 return { pCStr, capacity };
258 void give(std::pair<
char*, Size> data) {
259 Exception::checkThrow(GblStringBuffer_acquire(
this, data.first, data.second));
263 Exception::checkThrow(GblStringBuffer_clear(
this));
266 const String& operator=(std::string_view view) {
267 Exception::checkThrow(GblStringBuffer_set(
this, GBL_STRING_VIEW(view.data(), view.size())));
272 return *
this = StringView(rhs);
275 const String& operator=(StringView string) {
276 return *
this = string.toStringView();
279 const String& operator=(
const std::string& stdString) {
280 return *
this = stdString.c_str();
289 const String& operator=(
const char* pCStr) {
290 if(pCStr)
return *
this = std::string_view(pCStr);
291 else return *
this =
nullptr;
294 const String& operator=(std::nullptr_t) {
300 return *
this =
static_cast<GblStringBuffer&&>(rhs);
304 StringView rhsView(rhs);
306 if(getContext() == rhsView.getContext() && rhsView.isHeap()) {
309 *
this = rhsView.toStringView();
315 const String& operator+=(std::string_view view) {
320 const String& operator+=(StringView view) {
321 return *
this += view.toStringView();
324 void reserve(Size capacity) {
325 Exception::checkThrow(GblStringBuffer_reserve(
this, capacity));
328 void resize(Size size) {
329 Exception::checkThrow(GblStringBuffer_resize(
this, size));
332 void insert(const_iterator pos,
const char* pString, GblSize count=0) {
334 const auto index = std::distance(cbegin(), pos);
335 Exception::checkThrow(GblStringBuffer_insert(
this, index, GBL_STRING_VIEW(pString, count)));
339 void concat(std::string_view view) {
341 Exception::checkThrow(GblArrayList_append(&
this->data, view.data(), view.size()));
344 String& vasprintf(
const char* pFmt, va_list varArgs) {
345 Exception::checkThrow(GblStringBuffer_appendVPrintf(
this, pFmt, varArgs));
350 String& sprintf(
const char* pFmt, ...) {
352 va_start(varArgs, pFmt);
353 vasprintf(pFmt, varArgs);
359 template<
typename... Args>
360 String& varArgs(Args&&... args) {
361 String temp(
"", getContext());
362 temp.sprintf(getCString(), std::forward<Args>(args)...);
368 friend std::istream& operator>>(std::istream& input,
String &s) {
373 std::getline(input, line);
384 memcpy(pTemp, &lhs,
sizeof(
String));
385 memcpy(&lhs, &rhs,
sizeof(
String));
386 memcpy(&rhs, pTemp,
sizeof(
String));
394inline String operator+(
const gimbal::StringView& lhs,
const gimbal::StringView& rhs) {
395 return String(lhs) += rhs;
398inline String operator+(
const gimbal::StringView& lhs,
const std::string_view& rhs) {
399 return String(lhs) += rhs;
402inline String operator
"" _gstr(
const char* pLiteral, std::size_t length) {
404 return String(std::string_view{pLiteral, length});
408
409
410
413template<Size ExtraStackSize>
414class FlexibleString
final:
public String {
416 using FlexibleStringType = FlexibleString<ExtraStackSize>;
417 constexpr static const inline Size ExtraStackBufferSize = ExtraStackSize;
419 char extraStackBuffer_[ExtraStackSize] = {
'0' };
424inline StringView::StringView(
const gimbal::
String& string):
425 StringView(
static_cast<
const GblStringBuffer&>(string)) {}
430 template<gimbal::string_base S>
432 std::size_t operator()(
const S& str)
const {
433 return std::hash<std::string_view>{}(std::string_view(str.getCString()));
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
Mutable string type optimized for building and writing.