#include <luna/Format.h>
#include <luna/StringBuilder.h>
#include <luna/Vector.h>

Result<void> StringBuilder::add(StringView value)
{
    return m_data.append_data((const u8*)value.chars(), value.length());
}

Result<void> StringBuilder::add(const String& value)
{
    return add(value.view());
}

Result<void> StringBuilder::add(void* value)
{
    return format("%p"_sv, value);
}

Result<void> StringBuilder::add(long value)
{
    return format("%li"_sv, value);
}

Result<void> StringBuilder::add(unsigned long value)
{
    return format("%lu"_sv, value);
}

Result<void> StringBuilder::add(char value)
{
    return m_data.append_data((const u8*)&value, 1);
}

Result<void> StringBuilder::format(StringView fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    auto rc = vformat(fmt, ap);

    va_end(ap);

    return rc;
}

Result<void> StringBuilder::vformat(StringView fmt, va_list ap)
{
    Vector<char> temp;

    TRY(cstyle_format(
        fmt.chars(), [](char c, void* buf) -> Result<void> { return ((Vector<char>*)buf)->try_append(c); }, &temp, ap));

    TRY(m_data.append_data((u8*)temp.data(), temp.size()));

    return {};
}

Result<String> StringBuilder::string()
{
    char nul = '\0';
    TRY(m_data.append_data((u8*)&nul, 1));

    return String::from_cstring((const char*)m_data.data());
}