Kylin/DataStructure/KylinString.cpp
2024-09-16 01:32:40 +08:00

354 lines
9.0 KiB
C++

#include "KylinString.h"
#include "Exception.h"
#include <stdlib.h>
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() {
free(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<char *>(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<size_t>(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<size_t>(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<char *>(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<String &>(*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<char *>(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<size_t *>(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<int>(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<size_t>(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<size_t>(str[pos + patternLength])];
break;
}
}
}
return -1;
}
} // namespace Kylin