#include "String.h" #include "Char.h" #include #include String::String() { m_data.push_back('\0'); } String::String(size_t size, char c) { m_data.resize(size, c); m_data.push_back('\0'); } String::String(const Vector& data) { append(data); } String::String(const char* data) { append(data); } String String::fmt(const char* fmt, ...) { String ret; va_list args; va_start(args, fmt); char format_delim = '%'; bool in_format = false; while(*fmt != '\0') { if (*fmt == format_delim) { in_format = true; } else if(in_format && *fmt == 's') { in_format = false; const auto s = va_arg(args, char*); ret.append(s); } else if(in_format && *fmt == 'd') { in_format = false; const auto i = va_arg(args, int); ret += to_string(i); } else if(in_format && *fmt == 'c') { in_format = false; const auto c = va_arg(args, int); ret +=c; } else { ret += *fmt; } ++fmt; } va_end(args); return ret; } void String::append(const char* data) { if (data == nullptr) { m_data.push_back('\0'); return; } auto loc = data; bool first=true; while(*loc != '\0') { if (!m_data.empty() && first) { m_data[m_data.size() - 1] = *loc; } else { m_data.push_back(*loc); } first = false; loc++; } m_data.push_back('\0'); } void String::eraseIf(erasePredicate func) { size_t count{0}; for(size_t idx=0; idx& String::data() const { return m_data; } bool String::empty() const { return m_data.empty() || m_data[0] == '\0'; } void String::to_bytes(Vector& bytes) const { if (m_data.empty()) { return; } for(size_t idx=0; idx& data) { if (data.empty()) { m_data.push_back('\0'); return; } if (m_data.size() == 1 && m_data[0] == '\0') { m_data.clear(); } for(const auto c : data) { if(c == '\0') { break; } else { m_data.push_back(static_cast(c)); } } m_data.push_back('\0'); } Pair String::rsplit(char c) const { if (const auto index = rindex(c); index.valid()) { String left; slice(0, index.value(), left); String right; slice(index.value() + 1, size(), right); return {left, right}; } return {*this, {}}; } bool String::slice(size_t idx, String& out) const { if (idx >= m_data.size()) { return false; } auto ok = m_data.slice(idx, out.m_data); if (!ok) { return ok; } out.m_data.push_back('\0'); return true; } bool String::slice(size_t start, size_t end, String& out) const { if (end >= m_data.size()) { return false; } auto ok = m_data.slice(start, end, out.m_data); if (!ok) { return ok; } out.m_data.push_back('\0'); return true; } Index String::rindex(char c) const { if (m_data.size() <= 2) { return {}; } for(size_t idx=m_data.size()-2; idx >= 0; idx--) { if (m_data[idx] == c) { return Index(idx); } } return {}; } const char* String::raw() const { return m_data.data(); } size_t String::size() const { return m_data.size() - 1; } void String::reverse() { if (m_data.size() == 1) { return; } for(size_t idx=0; idx<(m_data.size()-1)/2; idx++) { const auto ridx = m_data.size() - 2 - idx; const auto tmp0 = m_data[idx]; m_data[idx] = m_data[ridx]; m_data[ridx] = tmp0; } } void String::split(Vector& output, char delimiter) const { String working_string; bool last_was_non_delimiter{ false }; for (size_t idx = 0; idx 0) { const auto rem = input_cpy % 10; conv += static_cast(48 + rem); input_cpy /= 10; } conv.reverse(); return conv; } char String::operator[](size_t idx) const { return m_data[idx]; } String& String::operator<<(const char* body) { append(body); return *this; } String& String::operator<<(const String& body) { *this += body; return *this; } bool String::operator==(const String& other) const { return m_data == other.m_data; } bool String::operator!=(const String& other) const { return !(*this == other); } String& String::operator<<(size_t idx) { *this += to_string(idx); return *this; } String& String::operator<<(const int idx) { *this += to_string(idx); return *this; } void String::push_back(char c) { if (m_data.empty()) { m_data.push_back('\0'); } m_data.push_back('\0'); m_data[m_data.size()-2] = c; } void String::to_lower() { if (empty()) { return; } for(size_t idx=0; idx