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) {
257 if (
extract() && x.extract()) {
261 reserve(x.size(),
false);
262 MemoryCopy(
m_Data, x.extract(), x.size());
270 ERROR(
"mismatch: '" << *
this <<
"' != '" << x <<
"'");
276void String::assign(
const Cord& x) {
279 reserve(x.length() + 1);
283 for (
auto& it : x.m_Segments) {
284 StringCopyN(buf + offset, it.ptr, it.length);
294void String::assign(
const char* s,
size_t len,
bool unsafe) {
297 const char* current =
extract();
299 const uintptr_t address =
reinterpret_cast<uintptr_t
>(s);
300 const uintptr_t begin =
reinterpret_cast<uintptr_t
>(current);
301 if ((address >= begin) && (address < (begin +
m_Size))) {
311 size_t copyLength = 0;
312 size_t origLength = len;
317 size_t trueLength = 0;
319 trueLength = BoundedStringLength(s, len);
321 trueLength = StringLength(s);
324 if (trueLength < len) {
330 }
else if (!s || !*s) {
342 reserve(pedigree_std::max(origLength, copyLength + 1),
false);
343 MemoryCopy(
m_Data, s, copyLength);
344 m_Data[copyLength] =
'\0';
356void String::reserve(
size_t size) {
360void String::reserve(
size_t size,
bool zero) {
363 size = pedigree_std::max(size, StringMinimumAllocationSize);
381 size_t newSize = pedigree_std::max(
m_Length + 1, StringMinimumAllocationSize);
388 m_Data =
new char[newSize];
396void String::clear() noexcept {
439 split(offset, result);
453 back.assign(&buf[offset],
m_Length - offset,
true);
486 MemoryCopy(buf, (buf + n),
m_Length);
519 tokenise(token, list);
529 utf8[0] = utf32 & 0x7F;
531 }
else if (utf32 <= 0x7FF) {
532 utf8[0] = 0xC0 | ((utf32 >> 6) & 0x1F);
533 utf8[1] = 0x80 | (utf32 & 0x3F);
535 }
else if (utf32 <= 0xFFFF) {
536 utf8[0] = 0xE0 | ((utf32 >> 12) & 0x0F);
537 utf8[1] = 0x80 | ((utf32 >> 6) & 0x3F);
538 utf8[2] = 0x80 | (utf32 & 0x3F);
540 }
else if (utf32 <= 0x10FFFF) {
541 utf8[0] = 0xF0 | ((utf32 >> 18) & 0x07);
542 utf8[1] = 0x80 | ((utf32 >> 12) & 0x3F);
543 utf8[2] = 0x80 | ((utf32 >> 6) & 0x3F);
544 utf8[3] = 0x80 | (utf32 & 0x3F);
552 const char* orig_buffer =
extract();
553 const char* buffer = orig_buffer;
559 const char* pos = buffer ? StringFind(buffer, token) :
nullptr;
560 while (pos && (*buffer)) {
567 output.createBack(buffer, pos - buffer);
572 pos = StringFind(buffer, token);
575 if (buffer && !pos) {
577 if (buffer == orig_buffer) {
578 output.createBack(
view());
580 size_t length =
m_Length - (buffer - orig_buffer);
582 output.createBack(buffer, length);
590 tokenise(token, views);
593 output.reserve(views.
count(),
false);
594 for (
auto& it : views) {
595 output.createBack(it);
607 StringCopy(buf, &buf[1]);
627void String::Format(
const char* fmt, ...) {
653 const char* otherbuf = s.
extract();
654 return endswith(otherbuf, s.length());
659 len = StringLength(s);
669 return !MemoryCompare(mybuf, s, len);
686 const char* otherbuf = s.
extract();
692 len = StringLength(s);
702 return !MemoryCompare(mybuf, s, len);
706 return (c <=
' ' || c ==
'\x7f');
723 for (ssize_t i = 0; i < signedLength; ++i) {
732ssize_t String::rfind(
const char c)
const {
737 for (ssize_t i =
m_Length - 1, n = 0; i >= 0; --i, ++n) {
764 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.