295 lines
8.9 KiB
C++
295 lines
8.9 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() { 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<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
|