13static_assert(
kSSOCapacity >= 1,
"SSO capacity must be at least 1");
14static_assert(
kSSOCapacity <= 255,
"SSO capacity must fit in a u8");
26 static constexpr std::size_t
npos = std::string::npos;
58 std::memset(buf.
data, c, n);
60 buf.
len =
static_cast<u8>(n);
77 [[nodiscard]] std::size_t
length() const noexcept {
return size(); }
78 [[nodiscard]]
bool empty() const noexcept {
return size() == 0; }
80 [[nodiscard]] std::size_t
capacity() const noexcept {
83 [[nodiscard]] std::size_t
max_size() const noexcept {
84 return std::string{}.max_size();
87 [[nodiscard]]
bool is_small() const noexcept {
return std::holds_alternative<SmallBuf>(
m_store); }
92 [[nodiscard]]
const char*
c_str() const noexcept {
return data(); }
93 [[nodiscard]] std::string_view
view() const noexcept {
return {
data(),
size()}; }
98 char&
at(std::size_t i) {
99 if (i >=
size())
throw std::out_of_range{
"PhsString::at: index out of range"};
102 const char&
at(std::size_t i)
const {
103 if (i >=
size())
throw std::out_of_range{
"PhsString::at: index out of range"};
130 else {
lg().clear(); }
134 const std::size_t old_sz =
size();
135 const std::size_t new_sz = old_sz + n;
139 std::memcpy(
sm().
data + old_sz,
s, n);
141 sm().
len =
static_cast<u8>(new_sz);
144 std::string promoted{
sm().
data, old_sz};
145 promoted.append(
s, n);
156 const std::size_t old_sz =
size();
157 const std::size_t new_sz = old_sz + n;
160 std::memset(
sm().
data + old_sz, c, n);
162 sm().
len =
static_cast<u8>(new_sz);
165 std::string promoted{
sm().
data, old_sz};
166 promoted.append(n, c);
182 else lg().pop_back();
185 void resize(std::size_t n,
char c =
'\0') {
186 const std::size_t old_sz =
size();
187 if (n == old_sz) {
return; }
188 else if (n < old_sz) {
190 else {
lg().resize(n); }
196 std::size_t
find(std::string_view sv, std::size_t pos = 0) const noexcept {
return view().find(sv, pos); }
197 std::size_t
find(
char c, std::size_t pos = 0) const noexcept {
return view().find(c, pos); }
198 std::size_t
rfind(std::string_view sv, std::size_t pos =
npos)
const noexcept {
return view().rfind(sv, pos); }
199 std::size_t
rfind(
char c, std::size_t pos =
npos)
const noexcept {
return view().rfind(c, pos); }
201 std::size_t
find_first_of (std::string_view sv, std::size_t pos = 0) const noexcept {
return view().find_first_of(sv, pos); }
202 std::size_t
find_last_of (std::string_view sv, std::size_t pos =
npos)
const noexcept {
return view().find_last_of(sv, pos); }
203 std::size_t
find_first_not_of(std::string_view sv, std::size_t pos = 0) const noexcept {
return view().find_first_not_of(sv, pos); }
204 std::size_t
find_last_not_of (std::string_view sv, std::size_t pos =
npos)
const noexcept {
return view().find_last_not_of(sv, pos); }
206 int compare(std::string_view sv)
const noexcept {
return view().compare(sv); }
208 [[nodiscard]]
bool starts_with(std::string_view sv)
const noexcept {
return view().starts_with(sv); }
209 [[nodiscard]]
bool ends_with (std::string_view sv)
const noexcept {
return view().ends_with(sv); }
210 [[nodiscard]]
bool contains (std::string_view sv)
const noexcept {
return find(sv) !=
npos; }
213 const std::size_t sz =
size();
214 if (pos > sz)
throw std::out_of_range{
"PhsString::substr: pos out of range"};
218 [[nodiscard]] std::string
str()
const {
221 operator std::string()
const {
return str(); }
222 operator std::string_view() const noexcept {
return view(); }
225 return view() <=> o.view();
228 return view() == o.view();
231 [[nodiscard]] std::strong_ordering
operator<=>(std::string_view sv)
const noexcept {
232 return view() <=> sv;
234 [[nodiscard]]
bool operator==(std::string_view sv)
const noexcept {
239 return os.write(
s.data(),
static_cast<std::streamsize
>(
s.size()));
251 :
len{
static_cast<u8>(n)} {
252 std::memcpy(
data,
s, n);
261 std::string&
lg() noexcept {
return std::get<std::string>(
m_store); }
262 const std::string&
lg() const noexcept {
return std::get<std::string>(
m_store); }
271 return lhs += rhs.
view();
279 return std::hash<std::string_view>{}(
s.view());
284struct std::formatter<
Phasor::PhsString> : std::formatter<std::string_view>
286 template <
typename FormatContext>
289 return std::formatter<std::string_view>::format(
s.view(), ctx);
constexpr std::size_t kSSOCapacity
const char * c_str() const noexcept
PhsString & append(std::size_t n, char c)
const char & const_reference
PhsString substr(std::size_t pos=0, std::size_t len=npos) const
const char & back() const noexcept
std::size_t find_first_of(std::string_view sv, std::size_t pos=0) const noexcept
const char & at(std::size_t i) const
static constexpr std::size_t SSO_CAPACITY
PhsString & operator+=(const char *s)
PhsString(const char *s, std::size_t n)
std::reverse_iterator< const_iterator > const_reverse_iterator
PhsString(PhsString &&) noexcept=default
std::ptrdiff_t difference_type
const_iterator cbegin() const noexcept
reverse_iterator rend() noexcept
std::strong_ordering operator<=>(const PhsString &o) const noexcept
bool is_heap_allocated() const noexcept
const_reverse_iterator rbegin() const noexcept
std::size_t size() const noexcept
bool ends_with(std::string_view sv) const noexcept
std::size_t length() const noexcept
const_iterator cend() const noexcept
std::size_t find_first_not_of(std::string_view sv, std::size_t pos=0) const noexcept
PhsString(std::string_view sv)
std::string_view view() const noexcept
std::size_t find_last_not_of(std::string_view sv, std::size_t pos=npos) const noexcept
const SmallBuf & sm() const noexcept
std::reverse_iterator< iterator > reverse_iterator
std::size_t rfind(char c, std::size_t pos=npos) const noexcept
std::variant< SmallBuf, std::string > m_store
const_reverse_iterator rend() const noexcept
const_reverse_iterator crbegin() const noexcept
void resize(std::size_t n, char c='\0')
bool empty() const noexcept
bool starts_with(std::string_view sv) const noexcept
PhsString(std::size_t n, char c)
const char & front() const noexcept
PhsString & append(std::string_view sv)
PhsString & append(const char *s, std::size_t n)
const std::string & lg() const noexcept
PhsString & operator+=(std::string_view sv)
static constexpr std::size_t npos
std::size_t find(std::string_view sv, std::size_t pos=0) const noexcept
std::string & lg() noexcept
bool operator==(const PhsString &o) const noexcept
const_iterator end() const noexcept
int compare(std::string_view sv) const noexcept
bool operator==(std::string_view sv) const noexcept
PhsString(const std::string &s)
std::strong_ordering operator<=>(std::string_view sv) const noexcept
iterator begin() noexcept
std::size_t find(char c, std::size_t pos=0) const noexcept
PhsString & operator+=(char c)
std::size_t max_size() const noexcept
friend std::ostream & operator<<(std::ostream &os, const PhsString &s)
char & operator[](std::size_t i) noexcept
std::size_t capacity() const noexcept
const char * const_pointer
PhsString(const PhsString &)=default
std::size_t rfind(std::string_view sv, std::size_t pos=npos) const noexcept
const char * data() const noexcept
const char * const_iterator
const char & operator[](std::size_t i) const noexcept
PhsString & operator=(std::string_view sv)
const_iterator begin() const noexcept
PhsString & append(const char *s)
const_reverse_iterator crend() const noexcept
std::size_t find_last_of(std::string_view sv, std::size_t pos=npos) const noexcept
bool is_small() const noexcept
bool contains(std::string_view sv) const noexcept
reverse_iterator rbegin() noexcept
The Phasor Programming Language and Runtime.
PhsString operator+(PhsString lhs, std::string_view rhs)
constexpr SmallBuf() noexcept
SmallBuf(const char *s, std::size_t n) noexcept
char data[SSO_CAPACITY+1]
std::size_t operator()(const Phasor::PhsString &s) const noexcept