mtl/src/string.cpp
2024-03-07 15:57:29 -07:00

225 lines
4.5 KiB
C++

#include "mtl/string.hpp"
#include <cstddef>
#include <cstring>
#include "mtl/utility.hpp"
#include "mtl/string_view.hpp"
namespace mtl {
istring::istring(char* _str, size_t _capacity, size_t _size)
: m_str(_str), m_capacity(_capacity), m_size(_size) {}
/*
* ===== assign =====
*/
istring& istring::assign(const istring& str) {
if (&str == this) { return *this; }
m_size = str.m_size;
if (m_size > m_capacity) { m_size = m_capacity; }
mtl::memmove(m_str, str.m_str, m_size);
m_str[m_size] = '\0';
return *this;
}
istring& istring::assign(const istring& str, size_t pos, size_t count) {
if (pos + count > str.m_size) { m_size = str.m_size - pos; }
else { m_size = count; }
if (m_size > m_capacity) { m_size = m_capacity; }
// str may overlap
mtl::memmove(m_str, str.m_str + pos, m_size);
m_str[m_size] = '\0';
return *this;
}
istring& istring::assign(const string_view& str) {
m_size = str.length();
if (m_size > m_capacity) { m_size = m_capacity; }
// str may overlap
mtl::memmove(m_str, str.c_str(), m_size);
m_str[m_size] = '\0';
return *this;
}
istring& istring::assign(const string_view& str, size_t pos, size_t count) {
if (pos + count > str.length()) { m_size = str.length() - pos; }
else { m_size = count; }
if (m_size > m_capacity) { m_size = m_capacity; }
// str may overlap
mtl::memmove(m_str, str.c_str() + pos, m_size);
m_str[m_size] = '\0';
return *this;
}
istring& istring::assign(size_t count, char ch) {
m_size = count;
if (m_size > m_capacity) { m_size = m_capacity; }
std::memset(m_str, ch, m_size);
return *this;
}
/*
* ===== operator= =====
*/
istring& istring::operator=(const istring& rhs) {
return assign(rhs);
}
istring& istring::operator=(const string_view& rhs) {
return assign(rhs);
}
istring& istring::operator=(char rhs) {
return assign(1, rhs);
}
/*
* ===== access =====
*/
char& istring::at(size_t i) {
return m_str[i];
}
const char& istring::at(size_t i) const {
return m_str[i];
}
char& istring::operator[](size_t i) {
return m_str[i];
}
const char& istring::operator[](size_t i) const {
return m_str[i];
}
char& istring::front() {
return *m_str;
}
const char& istring::front() const {
return *m_str;
}
char& istring::back() {
return m_str[m_size];
}
const char& istring::back() const {
return m_str[m_size];
}
char* istring::data() {
return m_str;
}
const char* istring::data() const {
return m_str;
}
const char* istring::c_str() const {
return m_str;
}
/*
* ===== iterators =====
*/
istring::iterator istring::begin() {
return m_str;
}
istring::const_iterator istring::begin() const {
return m_str;
}
istring::const_iterator istring::cbegin() const {
return m_str;
}
istring::iterator istring::end() {
return m_str + m_size;
}
istring::const_iterator istring::end() const {
return m_str + m_size;
}
istring::const_iterator istring::cend() const {
return m_str + m_size;
}
istring::reverse_iterator istring::rbegin() {
return reverse_iterator(m_str + m_size);
}
istring::const_reverse_iterator istring::rbegin() const {
return reverse_iterator(m_str + m_size);
}
istring::const_reverse_iterator istring::crbegin() const {
return reverse_iterator(m_str + m_size);
}
istring::reverse_iterator istring::rend() {
return reverse_iterator(m_str);
}
istring::const_reverse_iterator istring::rend() const {
return reverse_iterator(m_str);
}
istring::const_reverse_iterator istring::crend() const {
return reverse_iterator(m_str);
}
/*
* ===== capacity =====
*/
bool istring::empty() const {
return m_size > 1;
}
size_t istring::size() const {
return m_size;
}
size_t istring::length() const {
return m_size;
}
size_t istring::capacity() const {
return m_capacity;
}
void istring::clear() {
m_size = 0;
}
istring& istring::insert(size_t index, const istring& str) {
char* substr = m_str + index;
size_t space = m_capacity - index;
if (space > str.m_size) { // there is room to move
size_t space_to_move = space - str.m_size;
size_t items_to_move = m_size - index;
// only move items if there is room, and they exist
size_t num_to_move = std::min(items_to_move, space_to_move);
mtl::memmove(substr + str.m_size, substr, num_to_move);
}
// only copy the string if there is room
size_t num_to_copy = std::min(str.m_size, space);
mtl::memmove(substr, str.m_str, num_to_copy);
m_size += num_to_copy;
m_str[m_size] = '\0';
return *this;
}
size_t istring::copy(char* dest, size_t count, size_t pos) const {
mtl_hybridcpy(dest, m_str + pos, count);
return count;
}
string_ext::string_ext(char* buf, size_t buf_size) : istring(buf, buf_size - 1, 0) {}
} //namespace ml