Sane C++ Libraries
C++ Platform Abstraction Libraries
String.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Containers/Vector.h"
5#include "../Strings/StringView.h"
6
7namespace SC
8{
9struct SC_COMPILER_EXPORT String;
10namespace Reflection
11{
12template <typename T>
13struct Reflect;
14}
15// Allows using this type across Plugin boundaries
16SC_COMPILER_EXTERN template struct SC_COMPILER_EXPORT Vector<char>;
17
18} // namespace SC
19
22
30{
33 String(StringEncoding encoding = StringEncoding::Utf8) : encoding(encoding) {}
34
38 String(StringView sv) { SC_ASSERT_RELEASE(assign(sv)); }
39
44 template <size_t N>
45 String(const char (&text)[N])
46 {
47 SC_ASSERT_RELEASE(assign(StringView({text, N - 1}, true, StringEncoding::Ascii)));
48 }
49
53 [[nodiscard]] bool owns(StringView view) const;
54
59 [[nodiscard]] bool assign(StringView sv);
60
63 [[nodiscard]] StringEncoding getEncoding() const { return encoding; }
64
67 [[nodiscard]] size_t sizeInBytesIncludingTerminator() const { return data.size(); }
68
71 [[nodiscard]] const char* bytesIncludingTerminator() const { return data.data(); }
72
75 [[nodiscard]] bool isEmpty() const { return data.isEmpty(); }
76
79 [[nodiscard]] StringView view() const SC_LANGUAGE_LIFETIME_BOUND;
80
84 [[nodiscard]] bool operator==(const String& other) const { return view() == (other.view()); }
85
89 [[nodiscard]] bool operator!=(const String& other) const { return not operator==(other); }
90
94 [[nodiscard]] bool operator==(const StringView other) const { return view() == (other); }
95
99 [[nodiscard]] bool operator!=(const StringView other) const { return not operator==(other); }
100
104 [[nodiscard]] bool operator<(const StringView other) const { return view() < other; }
105
110 template <size_t N>
111 [[nodiscard]] bool operator==(const char (&other)[N]) const
112 {
113 return view() == other;
114 }
119 template <size_t N>
120 [[nodiscard]] bool operator!=(const char (&other)[N]) const
121 {
122 return view() != other;
123 }
124
130 template <size_t N>
131 String& operator=(const char (&text)[N])
132 {
133 SC_ASSERT_RELEASE(assign(StringView({text, N - 1}, true, StringEncoding::Ascii)));
134 return *this;
135 }
136
137 protected:
138 // TODO: nativeWritableBytesIncludingTerminator should be removed
139 [[nodiscard]] auto nativeWritableBytesIncludingTerminator();
140
141 // All these friendships are made to leverage writing directly to the Vector<char>
142 // but while still keeping it an implementation detail
143 friend struct SmallStringTest;
144 friend struct StringBuilder;
145 friend struct StringConverter;
146 friend struct FileDescriptor;
147 friend struct FileSystem;
148 template <int>
149 friend struct SmallString;
150 template <typename T>
151 friend struct Reflection::Reflect;
152 StringEncoding encoding;
153#if SC_COMPILER_MSVC
154#pragma warning(push)
155#pragma warning(disable : 4324) // useless warning on 32 bit... (structure was padded due to __declspec(align()))
156#endif
157 // alignas(alignof(SegmentHeader)) is needed on 32 bit to fix distance with SmallString::buffer
158 alignas(alignof(SegmentHeader)) Vector<char> data;
159#if SC_COMPILER_MSVC
160#pragma warning(pop)
161#endif
162};
164
165//-----------------------------------------------------------------------------------------------------------------------
166// Implementations Details
167//-----------------------------------------------------------------------------------------------------------------------
168
169inline bool SC::String::owns(StringView view) const
170{
171 return (view.bytesWithoutTerminator() >= this->view().bytesWithoutTerminator()) and
172 (view.bytesWithoutTerminator() <= (this->view().bytesWithoutTerminator() + this->view().sizeInBytes()));
173}
174
176{
177 encoding = sv.getEncoding();
178 const size_t length = sv.sizeInBytes();
179 const size_t numZero = StringEncodingGetSize(encoding);
180 if (not data.resizeWithoutInitializing(length + numZero))
181 return false;
182 if (sv.isNullTerminated())
183 {
184 memcpy(data.items, sv.bytesWithoutTerminator(), length + numZero);
185 }
186 else
187 {
188 if (length > 0)
189 {
190 memcpy(data.items, sv.bytesWithoutTerminator(), length);
191 }
192 for (size_t idx = 0; idx < numZero; ++idx)
193 {
194 data.items[length + idx] = 0;
195 }
196 }
197 return true;
198}
199
200inline SC::StringView SC::String::view() const SC_LANGUAGE_LIFETIME_BOUND
201{
202 const bool isEmpty = data.isEmpty();
203 const char* items = isEmpty ? nullptr : data.items;
204 return StringView({items, isEmpty ? 0 : data.size() - StringEncodingGetSize(encoding)}, not isEmpty, encoding);
205}
206
207inline auto SC::String::nativeWritableBytesIncludingTerminator()
208{
209#if SC_PLATFORM_WINDOWS
211 return reinterpret_cast<wchar_t*>(data.data());
212#else
214 return data.data();
215#endif
216}
#define SC_COMPILER_EXPORT
Macro for symbol visibility in non-MSVC compilers.
Definition: Compiler.h:78
#define SC_COMPILER_EXTERN
Define compiler-specific export macros for DLL visibility.
Definition: Compiler.h:74
#define SC_ASSERT_RELEASE(e)
Assert expression e to be true.
Definition: Assert.h:66
StringEncoding
String Encoding (Ascii, Utf8, Utf16)
Definition: StringIterator.h:17
constexpr uint32_t StringEncodingGetSize(StringEncoding encoding)
Returns the number of bytes to represent an utf unit in the given encoding.
Definition: StringIterator.h:308
@ Utf16
Encoding is UTF16-LE.
Wraps an OS File descriptor to read and write to and from it.
Definition: FileDescriptor.h:57
Execute fs operations { exists, copy, delete } for { files and directories }.
Definition: FileSystem.h:25
Basic class template that must be partially specialized for each type.
Definition: Reflection.h:195
String with compile time configurable inline storage (small string optimization)
Definition: SmallString.h:21
Builds String out of a sequence of StringView or formatting through StringFormat.
Definition: StringBuilder.h:16
Converts String to a different encoding (UTF8, UTF16).
Definition: StringConverter.h:25
A non-modifiable owning string with associated encoding.
Definition: String.h:30
StringEncoding getEncoding() const
Get StringView encoding.
Definition: String.h:63
bool operator==(const StringView other) const
Check if current String is same as other StringView.
Definition: String.h:94
bool operator!=(const String &other) const
Check if current String is different from other String.
Definition: String.h:89
bool operator<(const StringView other) const
Check if current String is smaller to another StringView (using StringView::compare)
Definition: String.h:104
bool assign(StringView sv)
Assigns a StringView to this String, replacing existing contents.
Definition: String.h:175
bool operator!=(const char(&other)[N]) const
Check if current String is different from the ascii string literal.
Definition: String.h:120
String(const char(&text)[N])
Builds String with a null terminated char string literal.
Definition: String.h:45
size_t sizeInBytesIncludingTerminator() const
Get length of the string in bytes (including null terminator bytes)
Definition: String.h:67
String(StringEncoding encoding=StringEncoding::Utf8)
Builds an empty String with a given Encoding.
Definition: String.h:33
String(StringView sv)
Builds String from a StringView.
Definition: String.h:38
StringView view() const SC_LANGUAGE_LIFETIME_BOUND
Obtain a null-terminated StringView from current String.
Definition: String.h:200
String & operator=(const char(&text)[N])
Assigns an ascii string literal to current String.
Definition: String.h:131
bool isEmpty() const
Check if String is empty.
Definition: String.h:75
const char * bytesIncludingTerminator() const
Access current string content as read-only null-terminated const char*
Definition: String.h:71
bool operator!=(const StringView other) const
Check if current String is different from other StringView.
Definition: String.h:99
bool owns(StringView view) const
Checks if the memory pointed by the StringView is owned by this String.
Definition: String.h:169
bool operator==(const char(&other)[N]) const
Check if current String is equal to the ascii string literal.
Definition: String.h:111
Non-owning view over a range of characters with UTF Encoding.
Definition: StringView.h:47
constexpr bool isNullTerminated() const
Check if StringView is immediately followed by a null termination character.
Definition: StringView.h:227
constexpr const char * bytesWithoutTerminator() const
Directly access the memory of this StringView.
Definition: StringView.h:97
constexpr StringEncoding getEncoding() const
Get encoding of this StringView.
Definition: StringView.h:93
constexpr bool isEmpty() const
Check if StringView is empty.
Definition: StringView.h:223
constexpr size_t sizeInBytes() const
Get size of the StringView in bytes.
Definition: StringView.h:231
A contiguous sequence of heap allocated elements.
Definition: Vector.h:51