Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
String.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/StringSpan.h"
5#include "../Memory/Buffer.h"
6#include "../Memory/Memory.h"
7
8namespace SC
9{
10template <int N>
11struct SmallString;
12namespace Reflection
13{
14template <typename T>
15struct Reflect;
16}
17
20
27struct SC_MEMORY_EXPORT String
28{
31 String(StringEncoding encoding = StringEncoding::Utf8) : encoding(encoding) {}
32
36 String(StringSpan sv) { SC_ASSERT_RELEASE(assign(sv)); }
37
40 String(Buffer&& otherData, StringEncoding encoding);
41
46 template <size_t N>
47 String(const char (&text)[N])
48 {
49 SC_ASSERT_RELEASE(assign(StringSpan({text, N - 1}, true, StringEncoding::Ascii)));
50 }
51
55 [[nodiscard]] bool owns(StringSpan view) const;
56
61 [[nodiscard]] bool assign(StringSpan sv);
62
65 [[nodiscard]] StringEncoding getEncoding() const { return encoding; }
66
69 [[nodiscard]] size_t sizeInBytesIncludingTerminator() const { return data.size(); }
70
73 [[nodiscard]] const char* bytesIncludingTerminator() const { return data.data(); }
74
77 [[nodiscard]] bool isEmpty() const { return data.isEmpty(); }
78
81 [[nodiscard]] StringSpan view() const SC_LANGUAGE_LIFETIME_BOUND;
82
86 [[nodiscard]] bool operator==(const String& other) const { return view() == (other.view()); }
87
91 [[nodiscard]] bool operator!=(const String& other) const { return not operator==(other); }
92
96 [[nodiscard]] bool operator==(const StringSpan other) const { return view() == (other); }
97
101 [[nodiscard]] bool operator!=(const StringSpan other) const { return not operator==(other); }
102
107 template <size_t N>
108 [[nodiscard]] bool operator==(const char (&other)[N]) const
109 {
110 return view() == other;
111 }
116 template <size_t N>
117 [[nodiscard]] bool operator!=(const char (&other)[N]) const
118 {
119 return view() != other;
120 }
121
125 [[nodiscard]] bool operator<(const StringSpan other) const { return view() < other; }
126
132 template <size_t N>
133 String& operator=(const char (&text)[N])
134 {
135 SC_ASSERT_RELEASE(assign(StringSpan({text, N - 1}, true, StringEncoding::Ascii)));
136 return *this;
137 }
138
142
143 protected:
144 struct Internal;
145
146 friend struct StringTest;
147 template <typename T>
148 friend struct Reflection::Reflect;
149
150 template <typename T>
151 friend struct GrowableBuffer;
152 struct SC_MEMORY_EXPORT GrowableImplementation
153 {
154 String& string;
155
156 IGrowableBuffer::DirectAccess& da;
157
158 GrowableImplementation(String& string, IGrowableBuffer::DirectAccess& da) noexcept;
159 ~GrowableImplementation() noexcept;
160 void finalize() noexcept;
161 bool tryGrowTo(size_t newSize) noexcept;
162 };
163
164 StringEncoding encoding;
165 Buffer data;
166
167 String(StringEncoding encoding, uint32_t inlineCapacity);
168 String(Buffer&& otherData, StringEncoding encoding, uint32_t inlineCapacity);
169};
170
173template <int N>
174struct SC_MEMORY_EXPORT SmallString : public String
175{
176 // Unfortunately we have to repeat all these overloads to set inline capacity and hasInlineData flag
177 SmallString(StringEncoding encoding = StringEncoding::Utf8) : String(encoding, N) {}
178 SmallString(const SmallString& other) : SmallString(other.getEncoding()) { String::operator=(other); }
179 SmallString(SmallString&& other) : SmallString(other.getEncoding()) { String::operator=(move(other)); }
180 String& operator=(const SmallString& other) { return String::operator=(other); }
181 String& operator=(SmallString&& other) { return String::operator=(move(other)); }
182
183 SmallString(const String& other) : SmallString(other.getEncoding()) { String::operator=(other); }
184 SmallString(String&& other) : SmallString(other.getEncoding()) { String::operator=(move(other)); }
185 SmallString(StringSpan other) : SmallString(other.getEncoding()) { String::operator=(move(other)); }
186 SmallString(Buffer&& otherData, StringEncoding encoding) : String(move(otherData), encoding, N) {}
187 template <size_t Q>
188 SmallString(const char (&text)[Q]) : SmallString(StringSpan({text, Q - 1}, true, StringEncoding::Ascii))
189 {}
190
191 private:
192 uint64_t inlineCapacity = N;
193 char buffer[N];
194};
196
197template <int N>
198using SmallStringNative = SmallString<N * sizeof(native_char_t)>;
199
200// Enables File library from reading data from file descriptor into a String
201template <>
202struct SC_MEMORY_EXPORT GrowableBuffer<String> : public IGrowableBuffer
203{
205 GrowableBuffer(String& string)
206 : IGrowableBuffer(&GrowableBuffer::tryGrowTo), gi(string, IGrowableBuffer::directAccess)
207 {}
208 static bool tryGrowTo(IGrowableBuffer& gb, size_t newSize) noexcept
209 {
210 return static_cast<GrowableBuffer&>(gb).gi.tryGrowTo(newSize);
211 }
212 static auto getEncodingFor(const String& str) noexcept { return str.getEncoding(); }
213 void finalize() noexcept { gi.finalize(); }
214};
215
216template <int N>
217struct SC_MEMORY_EXPORT GrowableBuffer<SmallString<N>> : public IGrowableBuffer
218{
220 GrowableBuffer(String& string)
221 : IGrowableBuffer(&GrowableBuffer::tryGrowTo), gi(string, IGrowableBuffer::directAccess)
222 {}
223 static bool tryGrowTo(IGrowableBuffer& gb, size_t newSize) noexcept
224 {
225 return static_cast<GrowableBuffer&>(gb).gi.tryGrowTo(newSize);
226 }
227 static auto getEncodingFor(const SmallString<N>& str) noexcept { return str.getEncoding(); }
228 void finalize() noexcept { gi.finalize(); }
229};
230} // namespace SC
#define SC_ASSERT_RELEASE(e)
Assert expression e to be true.
Definition Assert.h:48
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition Compiler.h:273
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
char native_char_t
The native char for the platform (wchar_t (4 bytes) on Windows, char (1 byte) everywhere else )
Definition PrimitiveTypes.h:25
An heap allocated byte buffer that can optionally use an inline buffer.
Definition Buffer.h:30
String with compile time configurable inline storage (small string optimization)
Definition String.h:175
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
Definition String.h:153
A non-modifiable owning string with associated encoding.
Definition String.h:28
StringEncoding getEncoding() const
Get StringSpan encoding.
Definition String.h:65
bool operator!=(const String &other) const
Check if current String is different from other String.
Definition String.h:91
bool operator<(const StringSpan other) const
Check if current String is smaller to another StringView (using StringView::compare)
Definition String.h:125
bool operator!=(const char(&other)[N]) const
Check if current String is different from the ascii string literal.
Definition String.h:117
StringSpan view() const SC_LANGUAGE_LIFETIME_BOUND
Obtain a null-terminated StringSpan from current String.
String(const char(&text)[N])
Builds String with a null terminated char string literal.
Definition String.h:47
bool owns(StringSpan view) const
Checks if the memory pointed by the StringSpan is owned by this String.
size_t sizeInBytesIncludingTerminator() const
Get length of the string in bytes (including null terminator bytes)
Definition String.h:69
String(StringEncoding encoding=StringEncoding::Utf8)
Builds an empty String with a given Encoding.
Definition String.h:31
bool operator!=(const StringSpan other) const
Check if current String is different from other StringSpan.
Definition String.h:101
String & operator=(const char(&text)[N])
Assigns an ascii string literal to current String.
Definition String.h:133
bool assign(StringSpan sv)
Assigns a StringSpan to this String, replacing existing contents.
bool operator==(const StringSpan other) const
Check if current String is same as other StringSpan.
Definition String.h:96
String & operator=(StringSpan view)
Assigns (copy) contents of given StringSpan in current String.
bool isEmpty() const
Check if String is empty.
Definition String.h:77
const char * bytesIncludingTerminator() const
Access current string content as read-only null-terminated const char*
Definition String.h:73
String(Buffer &&otherData, StringEncoding encoding)
Builds a String from a buffer ensuring zero termination.
String(StringSpan sv)
Builds String from a StringSpan.
Definition String.h:36
bool operator==(const char(&other)[N]) const
Check if current String is equal to the ascii string literal.
Definition String.h:108