20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/utilities/Cord.h"
22#include "pedigree/kernel/utilities/String.h"
23#include "pedigree/kernel/utilities/StringView.h"
24#include "pedigree/kernel/utilities/assert.h"
25#include "pedigree/kernel/utilities/utility.h"
30static constexpr size_t StringMinimumAllocationSize = 64;
43 assign(s, length, unsafe);
51 assign(x.str(), x.length(),
true);
55 move(
static_cast<String&&
>(x));
70 m_Data = other.m_Data;
71 m_Length = other.m_Length;
72 m_Size = other.m_Size;
73 m_Hash = other.m_Hash;
82 move(
static_cast<String&&
>(x));
91#if !STRING_DISABLE_EXPENSIVE_COPY_CONSTRUCTION
92String& String::operator=(
const char* s) {
114 return *
this +=
copy;
117 size_t newLength = x.length() +
m_Length;
119 reserve(newLength + 1);
122 const char* src = x.extract();
125 MemoryCopy(&dst[
m_Length], src, x.length() + 1);
132String& String::operator+=(
const char* s) {
135 const char* current =
extract();
137 const uintptr_t address =
reinterpret_cast<uintptr_t
>(s);
138 const uintptr_t begin =
reinterpret_cast<uintptr_t
>(current);
139 if ((address >= begin) && (address < (begin +
m_Size))) {
141 return *
this +=
copy;
145 size_t slen = StringLength(s);
173 const char* other_buf = s.
extract();
176 return !StringMatchN(buf, other_buf,
m_Length);
195 }
else if (StringLength(s) !=
m_Length) {
198 return !StringMatchN(buf, s,
m_Length);
211 return !StringMatchN(buf, s,
m_Length);
215char String::operator[](
size_t i)
const {
243 return ::nextCharacter(buf, c);
248 return ::prevCharacter(buf, c);
251void String::assign(
const String& x) {
264 if (
extract() && x.extract()) {
265 assert(
extract() != x.extract());
268 reserve(x.size(),
false);
269 MemoryCopy(
m_Data, x.extract(), x.size());
277 ERROR(
"mismatch: '" << *
this <<
"' != '" << x <<
"'");
283void String::assign(
const Cord& x) {
286 reserve(x.length() + 1);
290 for (
auto& it : x.m_Segments) {
291 StringCopyN(buf + offset, it.ptr, it.length);
301void String::assign(
const char* s,
size_t len,
bool unsafe) {
304 const char* current =
extract();
306 const uintptr_t address =
reinterpret_cast<uintptr_t
>(s);
307 const uintptr_t begin =
reinterpret_cast<uintptr_t
>(current);
308 if ((address >= begin) && (address < (begin +
m_Size))) {
318 size_t copyLength = 0;
319 size_t origLength = len;
324 size_t trueLength = 0;
326 trueLength = BoundedStringLength(s, len);
328 trueLength = StringLength(s);
331 if (trueLength < len) {
337 }
else if (!s || !*s) {
349 reserve(pedigree_std::max(origLength, copyLength + 1),
false);
350 MemoryCopy(
m_Data, s, copyLength);
351 m_Data[copyLength] =
'\0';
363void String::reserve(
size_t size) {
367void String::reserve(
size_t size,
bool zero) {
370 size = pedigree_std::max(size, StringMinimumAllocationSize);
388 size_t newSize = pedigree_std::max(
m_Length + 1, StringMinimumAllocationSize);
395 m_Data =
new char[newSize];
403void String::clear() noexcept {
454 split(offset, result);
468 back.assign(&buf[offset],
m_Length - offset,
true);
501 MemoryCopy(buf, (buf + n),
m_Length);
534 tokenise(token, list);
544 utf8[0] = utf32 & 0x7F;
546 }
else if (utf32 <= 0x7FF) {
547 utf8[0] = 0xC0 | ((utf32 >> 6) & 0x1F);
548 utf8[1] = 0x80 | (utf32 & 0x3F);
550 }
else if (utf32 <= 0xFFFF) {
551 utf8[0] = 0xE0 | ((utf32 >> 12) & 0x0F);
552 utf8[1] = 0x80 | ((utf32 >> 6) & 0x3F);
553 utf8[2] = 0x80 | (utf32 & 0x3F);
555 }
else if (utf32 <= 0x10FFFF) {
556 utf8[0] = 0xF0 | ((utf32 >> 18) & 0x07);
557 utf8[1] = 0x80 | ((utf32 >> 12) & 0x3F);
558 utf8[2] = 0x80 | ((utf32 >> 6) & 0x3F);
559 utf8[3] = 0x80 | (utf32 & 0x3F);
567 const char* orig_buffer =
extract();
568 const char* buffer = orig_buffer;
574 const char* pos = buffer ? StringFind(buffer, token) :
nullptr;
575 while (pos && (*buffer)) {
582 output.createBack(buffer, pos - buffer);
587 pos = StringFind(buffer, token);
590 if (buffer && !pos) {
592 if (buffer == orig_buffer) {
593 output.createBack(
view());
595 size_t length =
m_Length - (buffer - orig_buffer);
597 output.createBack(buffer, length);
605 tokenise(token, views);
608 output.reserve(views.
count(),
false);
609 for (
auto& it : views) {
610 output.createBack(it);
622 StringCopy(buf, &buf[1]);
642void String::Format(
const char* fmt, ...) {
668 const char* otherbuf = s.
extract();
669 return endswith(otherbuf, s.length());
674 len = StringLength(s);
684 return !MemoryCompare(mybuf, s, len);
701 const char* otherbuf = s.
extract();
707 len = StringLength(s);
717 return !MemoryCompare(mybuf, s, len);
721 return (c <=
' ' || c ==
'\x7f');
738 for (ssize_t i = 0; i < signedLength; ++i) {
747ssize_t String::rfind(
const char c)
const {
752 for (ssize_t i =
m_Length - 1, n = 0; i >= 0; --i, ++n) {
779 result.assign(*
this);
virtual bool assignable() const
void move(String &&other) noexcept
bool startswith(const char c) const
bool compare(const char *s, size_t len) const
bool operator==(const String &s) const
virtual bool resizable() const
bool iswhitespace(const char c) const
virtual char * extract() const
ssize_t find(const char c) const
size_t nextCharacter(size_t c) const
String split(size_t offset)
bool endswith(const char c) const
static size_t Utf32ToUtf8(uint32_t utf32, char *utf8)
size_t prevCharacter(size_t c) const
uint32_t maybeHash() const
A vector / dynamic array.