diff --git a/include/mtl/string.hpp b/include/mtl/string.hpp index b5d28e8..ffe5244 100644 --- a/include/mtl/string.hpp +++ b/include/mtl/string.hpp @@ -127,6 +127,12 @@ public: // Search + /** + * \brief Find the first occurence of the substring + * + * Uses a naive brute force search. Could be sped up by using the + * Boyer-Moore search algorithm. + */ size_t find(const string_view& str, size_t pos = 0) const; size_t find(char ch, size_t pos = 0) const; @@ -149,20 +155,13 @@ public: int32_t compare(const string_view& str) const; int32_t compare(size_t pos, size_t count, const string_view& str) const; - int32_t compare(size_t pos1, size_t count1, const string_view& str, size_t pos2, size_t count2 = npos) const; + int32_t compare(size_t pos1, size_t count1, const string_view& str, size_t pos2, size_t count2) const; - friend bool operator==(const istring& lhs, const string_view& rhs); - friend bool operator==(const string_view& lhs, const istring& rhs); - friend bool operator!=(const istring& lhs, const string_view& rhs); - friend bool operator!=(const string_view& lhs, const istring& rhs); - friend bool operator<(const istring& lhs, const string_view& rhs); - friend bool operator<(const string_view& lhs, const istring& rhs); - friend bool operator<=(const istring& lhs, const string_view& rhs); - friend bool operator<=(const string_view& lhs, const istring& rhs); - friend bool operator>(const istring& lhs, const string_view& rhs); - friend bool operator>(const string_view& lhs, const istring& rhs); - friend bool operator>=(const istring& lhs, const string_view& rhs); - friend bool operator>=(const string_view& lhs, const istring& rhs); + bool operator==(const istring& rhs) const; + bool operator!=(const istring& rhs) const; + + bool operator==(const string_view& rhs) const; + bool operator!=(const string_view& rhs) const; }; template diff --git a/src/string.cpp b/src/string.cpp index 678a5c9..ca6fb7f 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -195,6 +195,287 @@ istring& istring::insert(size_t index, const string_view& str, size_t str_index, return *this; } +void istring::resize(size_t count) { + if (count > m_capacity) { count = m_capacity; } + + m_size = count; + m_str[m_size] = '\0'; +} + +void istring::resize(size_t count, char ch) { + if (count > m_capacity) { count = m_capacity; } + + if (count > m_size) { + std::memset(m_str + m_size, ch, count - m_size); + } + + m_size = count; + m_str[m_size] = '\0'; +} + +size_t istring::find(const string_view& str, size_t pos) const { + if (str.m_size > m_size) { return npos; } + + // Brute force algorithm + // TODO: Implement Boyer-Moore search algorithm + size_t end = m_size - str.m_size + 1; + // Find a match of the first character + for (size_t i = pos; i < end; ++i) { + if (m_str[i] == str.m_str[0]) { + // Check that the rest of the string matches + bool match = true; + for (size_t j = 1; j < str.m_size; ++j) { + if (m_str[i + j] != str[j]) { + match = false; + break; + } + } + + if (match) { + return i; + } + } + } + + return npos; +} + +size_t istring::find(char ch, size_t pos) const { + for (size_t i = pos; i < m_size; ++i) { + if (m_str[i] == ch) { + return i; + } + } + + return npos; +} + +size_t istring::rfind(const string_view& str, size_t pos) const { + if (str.m_size > m_size) { return npos; } + + if (pos > m_size - str.m_size) { + pos = m_size - str.m_size; + } + + // Find a match of the first character + for (size_t i = pos + 1; i--; ) { + if (m_str[i] == str.m_str[0]) { + // Check that the rest of the string matches + bool match = true; + for (size_t j = 1; j < str.m_size; ++j) { + if (m_str[i + j] != str[j]) { + match = false; + break; + } + } + + if (match) { + return i; + } + } + } + + return npos; +} + +size_t istring::rfind(char ch, size_t pos) const { + if (m_size == 0) { return npos; } + + if (pos > m_size - 1) { + pos = m_size - 1; + } + + for (size_t i = pos + 1; i--; ) { + if (m_str[i] == ch ) { + return i; + } + } + + return npos; +} + +size_t istring::find_first_of(const string_view& str, size_t pos) const { + for (size_t i = pos; i < m_size; ++i) { + for (size_t j = 0; j < str.m_size; ++j) { + if (m_str[i] == str[j]) { return i; } + } + } + + return npos; +} + +size_t istring::find_first_of(char ch, size_t pos) const { + for (size_t i = pos; i < m_size; ++i) { + if (m_str[i] == ch) { return i; } + } + + return npos; +} + +size_t istring::find_first_not_of(const string_view& str, size_t pos) const { + for (size_t i = pos; i < m_size; ++i) { + bool match = false; + for (size_t j = 0; j < str.m_size; ++j) { + if (m_str[i] == str[j]) { + match = true; + break; + } + } + + if (!match) { return i; } + } + + return npos; +} + +size_t istring::find_first_not_of(char ch, size_t pos) const { + for (size_t i = pos; i < m_size; ++i) { + if (m_str[i] != ch) { return i; } + } + + return npos; +} + +size_t istring::find_last_of(const string_view& str, size_t pos) const { + if (m_size == 0) { return npos; } + + if (pos > m_size - 1) { + pos = m_size - 1; + } + + for (size_t i = pos + 1; i--; ) { + for (size_t j = 0; j < str.m_size; ++j) { + if (m_str[i] == str[j]) { return i; } + } + } + + return npos; +} + +size_t istring::find_last_of(char ch, size_t pos) const { + if (m_size == 0) { return npos; } + + if (pos > m_size - 1) { + pos = m_size - 1; + } + + for (size_t i = pos + 1; i--; ) { + if (m_str[i] == ch) { return i; } + } + + return npos; +} + +size_t istring::find_last_not_of(const string_view& str, size_t pos) const { + if (m_size == 0) { return npos; } + + if (pos > m_size - 1) { + pos = m_size - 1; + } + + for (size_t i = pos + 1; i--; ) { + bool match = false; + for (size_t j = 0; j < str.m_size; ++j) { + if (m_str[i] == str[j]) { + match = true; + break; + } + } + + if (!match) { return i; } + } + + return npos; +} + +size_t istring::find_last_not_of(char ch, size_t pos) const { + if (m_size == 0) { return npos; } + + if (pos > m_size - 1) { + pos = m_size - 1; + } + + for (size_t i = pos + 1; i--; ) { + if (m_str[i] != ch) { return i; } + } + + return npos; +} + +int32_t istring::compare(const string_view& str) const { + size_t end = m_size < str.m_size ? m_size : str.m_size; + + for (size_t i = 0; i < end; ++i) { + int32_t diff = (int32_t) str.m_str[i] - m_str[i]; + + if (diff != 0) { return diff; } + } + + return (int32_t)str.m_size - m_size; +} + +int32_t istring::compare(size_t pos, size_t count, const string_view& str) const { + size_t end = count < str.m_size ? count : str.m_size; + + for (size_t i = 0; i < end; ++i) { + int32_t diff = (int32_t)str.m_str[i] - m_str[pos + i]; + + if (diff != 0) { return diff; } + } + + return (int32_t)str.m_size - m_size; +} + +int32_t istring::compare(size_t pos, size_t count, const string_view& str, size_t pos2, size_t count2) const { + size_t end = count < count2 ? count : count2; + + for (size_t i = 0; i < end; ++i) { + int32_t diff = (int32_t)str.m_str[pos2 + i] - m_str[pos + i]; + + if (diff != 0) { return diff; } + } + + return (int32_t)str.m_size - m_size; +} + +bool istring::operator==(const istring& rhs) const { + if (m_size != rhs.m_size) { return false; } + + for (size_t i = 0; i < m_size; ++i) { + if (m_str[i] != rhs[i]) { return false; } + } + + return true; +} +bool istring::operator!=(const istring& rhs) const { + if (m_size != rhs.m_size) { return true; } + + for (size_t i = 0; i < m_size; ++i) { + if (m_str[i] != rhs[i]) { return true; } + } + + return false; +} + +bool istring::operator==(const string_view& rhs) const { + if (m_size != rhs.m_size) { return false; } + + for (size_t i = 0; i < m_size; ++i) { + if (m_str[i] != rhs[i]) { return false; } + } + + return true; +} +bool istring::operator!=(const string_view& rhs) const { + if (m_size != rhs.m_size) { return true; } + + for (size_t i = 0; i < m_size; ++i) { + if (m_str[i] != rhs[i]) { return true; } + } + + return false; +} + size_t istring::copy(char* dest, size_t count, size_t pos) const { mtl_hybridcpy(dest, m_str + pos, count); return count;