diff --git a/libluna/CMakeLists.txt b/libluna/CMakeLists.txt index a59c7efe..86e411ad 100644 --- a/libluna/CMakeLists.txt +++ b/libluna/CMakeLists.txt @@ -14,6 +14,7 @@ set(FREESTANDING_SOURCES src/Buffer.cpp src/Stack.cpp src/String.cpp + src/StringBuilder.cpp src/StringView.cpp src/Utf8.cpp src/TarStream.cpp diff --git a/libluna/include/luna/StringBuilder.h b/libluna/include/luna/StringBuilder.h new file mode 100644 index 00000000..18baf533 --- /dev/null +++ b/libluna/include/luna/StringBuilder.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include + +class StringBuilder +{ + public: + Result add(const String& value); + Result add(StringView value); + Result add(void* value); + Result add(long value); + Result add(unsigned long value); + Result add(char value); + + Result format(StringView fmt, ...); + Result vformat(StringView fmt, va_list ap); + + Result string(); + + private: + Buffer m_data; +}; diff --git a/libluna/src/StringBuilder.cpp b/libluna/src/StringBuilder.cpp new file mode 100644 index 00000000..22e9097f --- /dev/null +++ b/libluna/src/StringBuilder.cpp @@ -0,0 +1,65 @@ +#include +#include +#include + +Result StringBuilder::add(StringView value) +{ + return m_data.append_data((const u8*)value.chars(), value.length()); +} + +Result StringBuilder::add(const String& value) +{ + return add(value.view()); +} + +Result StringBuilder::add(void* value) +{ + return format("%p"_sv, value); +} + +Result StringBuilder::add(long value) +{ + return format("%li"_sv, value); +} + +Result StringBuilder::add(unsigned long value) +{ + return format("%lu"_sv, value); +} + +Result StringBuilder::add(char value) +{ + return format("%c"_sv, value); +} + +Result StringBuilder::format(StringView fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + auto rc = vformat(fmt, ap); + + va_end(ap); + + return rc; +} + +Result StringBuilder::vformat(StringView fmt, va_list ap) +{ + Vector temp; + + TRY(cstyle_format( + fmt.chars(), [](char c, void* buf) -> Result { return ((Vector*)buf)->try_append(c); }, &temp, ap)); + + TRY(m_data.append_data((u8*)temp.data(), temp.size())); + + return {}; +} + +Result StringBuilder::string() +{ + char nul = '\0'; + TRY(m_data.append_data((u8*)&nul, 1)); + + return String::from_cstring((const char*)m_data.data()); +}