Luna/libluna/src/String.cpp

211 lines
4.1 KiB
C++
Raw Normal View History

#include <luna/Alloc.h>
#include <luna/CString.h>
2023-04-07 08:37:00 +00:00
#include <luna/Format.h>
#include <luna/String.h>
2023-05-01 17:29:17 +00:00
#include <luna/StringBuilder.h>
2023-04-07 08:37:00 +00:00
#include <luna/Vector.h>
String::String()
{
empty();
}
void String::empty()
{
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.empty();
}
2023-04-07 10:14:21 +00:00
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.empty();
2023-04-07 10:14:21 +00:00
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> String::clone() const
{
return from_cstring(chars());
}
Result<String> 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 };
}
2023-04-22 13:19:07 +00:00
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];
}
2023-04-07 08:37:00 +00:00
Result<String> 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> String::format(StringView fmt, ...)
{
va_list ap;
va_start(ap, fmt);
auto rc = vformat(fmt, ap);
va_end(ap);
return rc;
}
Result<String> String::vformat(StringView fmt, va_list ap)
{
Vector<char> buf;
TRY(cstyle_format(
fmt.chars(), [](char c, void* data) -> Result<void> { return ((Vector<char>*)data)->try_append(c); }, &buf,
ap));
TRY(buf.try_append(0));
return String { buf.release_data() };
2023-04-07 08:37:00 +00:00
}
Result<String> String::from_cstring(const char* str)
{
return from_string_view(StringView { str });
}
Result<String> String::from_string_view(StringView str)
{
if (str.length() < sizeof(m_inline_storage))
{
String result;
result.m_inline = true;
result.m_length = str.length();
memset(result.m_inline_storage, 0, sizeof(result.m_inline_storage));
memcpy(result.m_inline_storage, str.chars(), str.length());
return result;
}
char* const dup = strndup(str.chars(), str.length());
if (!dup) return err(ENOMEM);
return String { dup, str.length() };
}
2023-05-01 17:29:17 +00:00
Result<String> String::join(const Vector<String>& vec, StringView delim)
{
if (vec.size() == 0) return String {};
if (vec.size() == 1) return vec[0].clone();
StringBuilder sb;
TRY(sb.add(vec[0].view()));
for (usize i = 1; i < vec.size(); i++)
{
TRY(sb.add(delim));
TRY(sb.add(vec[i].view()));
}
return sb.string();
}
Result<String> String::join(const Vector<StringView>& vec, StringView delim)
{
if (vec.size() == 0) return String {};
if (vec.size() == 1) return from_string_view(vec[0]);
StringBuilder sb;
TRY(sb.add(vec[0]));
for (usize i = 1; i < vec.size(); i++)
{
TRY(sb.add(delim));
TRY(sb.add(vec[i]));
}
return sb.string();
}
int String::compare(const String* a, const String* b)
{
return strcmp(a->chars(), b->chars());
}
template <> u64 hash(const String& value, u64 salt)
{
return hash_memory(value.chars(), value.length(), salt);
}