#include #include #include #include #include String::String() { m_inline = true; m_length = 0; memset(m_inline_storage, 0, sizeof(m_inline_storage)); } String::String(String&& other) { m_inline = other.m_inline; m_string = other.m_string; m_length = other.m_length; if (m_inline) memcpy(m_inline_storage, other.m_inline_storage, sizeof(m_inline_storage)); other.m_string = nullptr; } String& String::operator=(String&& other) { if (&other == this) return *this; if (!m_inline) free_impl(m_string); m_inline = other.m_inline; m_string = other.m_string; m_length = other.m_length; if (m_inline) memcpy(m_inline_storage, other.m_inline_storage, sizeof(m_inline_storage)); other.m_string = nullptr; return *this; } String::String(char* c_str) { check(c_str); m_string = c_str; m_inline = false; m_length = strlen(m_string); } String::String(char* c_str, usize length) { check(c_str); m_string = c_str; m_inline = false; m_length = length; } String::~String() { if (!m_inline) free_impl(m_string); } Result String::clone() const { return from_cstring(chars()); } Result String::substring(usize begin, usize size) const { if (begin + size >= size) return err(EINVAL); char* const dup = strndup(chars() + begin, size); if (!dup) return err(ENOMEM); return String { dup, size }; } Result> String::split(StringView delim) const { return view().split(delim); } void String::trim(StringView delim) { isize i = (isize)m_length; while (i--) { char c = chars()[i]; if (!strchr(delim.chars(), c)) break; } i++; if (m_inline) m_inline_storage[i] = '\0'; else m_string[i] = '\0'; m_length = (usize)i; } const char& String::operator[](usize index) const { expect(index < m_length, "index out of range"); return chars()[index]; } Result String::format(const String& fmt, ...) { va_list ap; va_start(ap, fmt); auto rc = vformat(fmt.view(), ap); va_end(ap); return rc; } Result String::format(StringView fmt, ...) { va_list ap; va_start(ap, fmt); auto rc = vformat(fmt, ap); va_end(ap); return rc; } Result String::vformat(StringView fmt, va_list ap) { Vector buf; TRY(cstyle_format( fmt.chars(), [](char c, void* data) -> Result { return ((Vector*)data)->try_append(c); }, &buf, ap)); TRY(buf.try_append(0)); return from_cstring(buf.data()); } Result String::from_cstring(const char* str) { usize len = strlen(str); if (len < sizeof(m_inline_storage)) { String result; result.m_inline = true; result.m_length = len; strncpy(result.m_inline_storage, str, sizeof(m_inline_storage)); return result; } char* const dup = strdup(str); if (!dup) return err(ENOMEM); return String { dup }; }