#include "KylinString.h" #include "Exception.h" #include namespace Kylin { String::String() { init(nullptr); } String::String(const char c) { char str[] = {c, '\0'}; init(str); } String::String(const char *str) { init(str); } String::String(const String &str) { init(str.m_str); } String::String(String &&other) { m_str = other.m_str; m_length = other.m_length; other.init(nullptr); } String::~String() { delete m_str; } String &String::operator=(const String &str) { return operator=(str.m_str); } String &String::operator=(const char *str) { if (m_str != str) { auto s = strdup(str); if (s == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "Thers is no memory to aclloc string..."); free(m_str); m_str = s; m_length = strlen(m_str); } return *this; } bool String::startWith(const char *s) const { if (s == nullptr) return false; auto len = strlen(s); if (len > m_length) return false; for (size_t i = 0; i < len; i++) { if (s[i] != m_str[i]) return false; } return true; } bool String::startWith(const String &s) const { return startWith(s.m_str); } bool String::endOf(const char *s) const { if (s == nullptr) return false; auto len = strlen(s); if (len > m_length) return false; size_t begin = m_length - len; for (size_t i = 0; i < len; i++) { if (s[i] != m_str[begin + i]) return false; } return true; } bool String::endOf(const String &s) const { return endOf(s.str()); } String &String::insert(size_t index, const char *s) { if (s != nullptr) { if (index > m_length) THROW_EXCEPTION(InvalidParameterException, "Index i is a invalid parameter..."); auto size = strlen(s); auto str = reinterpret_cast(malloc(m_length + size + 1)); if (str == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "There is no memory to create string..."); strncpy(str, m_str, index); strcpy(str + index, s); strcpy(str + index + size, m_str + index); str[size + m_length] = '\0'; free(m_str); m_str = str; m_length = strlen(m_str); } return *this; } String &String::insert(size_t index, const String &s) { return insert(index, s.m_str); } String &String::trim() { size_t begin = 0, end = m_length - 1; while (m_str[begin] == ' ') begin++; while (m_str[end] == ' ') end--; if (begin == 0) { m_str[end + 1] = '\0'; m_length = end + 1; } else { size_t i = 0; for (; begin <= end; i++, begin++) { m_str[i] = m_str[begin]; } m_str[i] = '\0'; m_length = i; } return *this; } int String::indexOf(const char *s) const { return kmp(m_str, s); } int String::indexOf(const String &s) const { return indexOf(s.m_str); } String &String::remove(size_t index, size_t length) { if (index >= m_length) THROW_EXCEPTION(InvalidParameterException, "Index is invalid..."); size_t begin = index + length; for (; begin < m_length; begin++, index++) { m_str[index] = m_str[begin]; } m_str[index] = '\0'; m_length = index; return *this; } String &String::remove(const char *s) { auto pos = indexOf(s); if (pos >= 0) remove(static_cast(pos), strlen(s)); return *this; } String &String::remove(const String &s) { return remove(s.m_str); } String &String::replace(const char *t, const char *s) { auto pos = indexOf(t); if (pos > 0) { remove(t); insert(static_cast(pos), s); } return *this; } String &String::replace(const String &t, const char *s) { return replace(t.m_str, s); } String &String::replace(const char *t, const String &s) { return replace(t, s.m_str); } String &String::replace(const String &t, const String &s) { return replace(t.m_str, s.m_str); } String String::substr(size_t index, size_t length) const { if (index >= m_length) THROW_EXCEPTION(InvalidParameterException, "Parameter index is invalid..."); if ((index + length) >= m_length) length = m_length - index; auto str = reinterpret_cast(malloc(length + 1)); strncpy(str, m_str + index, length); str[length] = '\0'; String ret(str); free(str); return ret; } char &String::operator[](size_t index) { if (index >= m_length) THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds..."); return m_str[index]; } char String::operator[](size_t index) const { return const_cast(*this)[index]; } bool String::operator<(const char *str) const { return (strcmp(m_str, str) < 0); } bool String::operator<(const String &str) const { return operator<(str.m_str); } bool String::operator>=(const char *str) const { return !(*this < str); } bool String::operator>=(const String &str) const { return !(*this < str); } bool String::operator>(const char *str) const { return (strcmp(m_str, str) > 0); } bool String::operator>(const String &str) const { return operator>(str.m_str); } bool String::operator<=(const char *str) const { return !(*this > str); } bool String::operator<=(const String &str) const { return !(*this > str); } bool String::operator==(const char *str) const { if (str == nullptr && m_str == nullptr) return true; if (str == nullptr || m_str == nullptr) return false; return (strcmp(m_str, str) == 0); } bool String::operator==(const String &str) const { return operator==(str.m_str); } bool String::operator!=(const char *str) const { return !(*this == str); } bool String::operator!=(const String &str) const { return !(*this == str); } String &String::operator+=(const char *str) { if (str != nullptr) { auto size = strlen(str); auto s = reinterpret_cast(malloc(m_length + size + 1)); if (s == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "Thers is no memory to alloc string..."); strcpy(s, m_str); strcat(s, str); s[m_length + size] = '\0'; free(m_str); m_str = s; m_length = strlen(m_str); } return *this; } String &String::operator+=(const String &str) { return operator+=(str.m_str); } String String::operator+(const char *str) const { String ret(*this); ret += str; return ret; } String String::operator+(const String &str) const { return operator+(str.m_str); } String &String::operator-=(const char *str) { return remove(str); } String &String::operator-=(const String &str) { return remove(str); } String String::operator-(const char *str) const { String ret(*this); return (ret -= str); } String String::operator-(const String &str) const { String ret(*this); return (ret -= str); } void String::init(const char *str) { m_str = strdup(str ? str : ""); if (m_str == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "Thers is no memory to aclloc string..."); m_length = strlen(m_str); } size_t *String::make_pmt(const char *p) { auto len = strlen(p); auto *ret = reinterpret_cast(malloc(sizeof(size_t) * len)); if (ret != nullptr) { size_t ll = 0; ret[0] = 0; for (size_t i = 1; i < len; i++) { while ((p[ll] != p[i]) && (ll > 0)) { ll = ret[ll - 1]; } if (p[ll] == p[i]) ll++; ret[i] = ll; } } return ret; } int String::kmp(const char *s, const char *p) { int ret = -1; auto sl = strlen(s); auto pl = strlen(p); auto pmt = make_pmt(p); if ((pmt != nullptr) && (0 < pl) && (pl <= sl)) { for (size_t i = 0, j = 0; i < sl; i++) { while ((j > 0) && (s[i] != p[j])) { j = pmt[j - 1]; } if (s[i] == p[j]) j++; if (j == pl) ret = static_cast(i + 1 - pl); } } free(pmt); return ret; } int String::sunday(const char *str, const char *pattern) { static char shift[256]; size_t patternLength = strlen(pattern); size_t strLength = strlen(str); if (patternLength > strLength) return -1; for (size_t i = 0; i < 256; i++) { shift[i] = patternLength + 1; } for (size_t i = 0; i < patternLength; i++) { shift[static_cast(pattern[i])] = patternLength - i; } size_t pos = 0; while (pos <= strLength - patternLength) { size_t index = 0; while (index < patternLength) { if (str[pos + index] == pattern[index]) { index++; if (index == patternLength) return pos; } else { pos += shift[static_cast(str[pos + patternLength])]; break; } } } return -1; } } // namespace Kylin