class string
{
public:
typedef size_t size_type;
typedef char* iterator;
typedef char value_type;
private:
char *start, *end_of_storage, *End;
std::allocator<char> data_allocator;
void DeallocateAndDestory()
{
data_allocator.deallocate(start, end_of_storage - start);
}
//重新构造元素
void reallocate(size_t new_size = 0)
{
size_t old_size = size();
if (new_size == 0)
new_size = size() ? 2 * size() : 1;
char* new_start = data_allocator.allocate(new_size);
std::copy(start, start + size(), new_start);
DeallocateAndDestory();
start = new_start;
End = new_start + old_size;
end_of_storage = new_start + new_size;
}
//移动构造元素
/*void reallocate()
{
int old_size = size();
int new_size = size() ? 2 * size() : 1;
char* new_start = data_allocator.allocate(new_size);
char* pos = new_start;
char* old_pos = start;
for (int i = 0; i < old_size; i++)
data_allocator.construct(pos++, std::move(*old_pos)), old_pos++;
data_allocator.deallocate(start, old_size);
start = new_start;
End = new_start + old_size;
end_of_storage = new_start + new_size;
}*/
public:
//debug
void print()
{
for (auto it = start; it != End; it++)
std::cout << *it;
std::cout << std::endl;
}
//Construct
string()
{
start = end_of_storage = End = nullptr;
}
string(const string& rhs)
{
start = end_of_storage = End = nullptr;
append(rhs);
}
string(string&& rhs)noexcept :start(rhs.start), end_of_storage(rhs.end_of_storage), End(rhs.End)
{
rhs.start = rhs.end_of_storage = rhs.End = nullptr;
}
string(const char* s)
{
if (s == nullptr)
string();
else
{
int cnt = 0;
for (; s[cnt] != ' '; cnt++) {}
start = data_allocator.allocate(cnt);
std::uninitialized_copy_n(s, cnt, start);
end_of_storage = End = start + cnt;
}
}
string(size_type n, char c)
{
start = data_allocator.allocate(n);
std::uninitialized_fill_n(start, n, c);
end_of_storage = End = start + n;
}
string(const char* s, size_t n)
{
start = data_allocator.allocate(n);
std::uninitialized_copy_n(s, n, start);
End = end_of_storage = start + n;
}
~string()
{
DeallocateAndDestory();
}
//Iterator
const iterator begin() const
{
return start;
}
const iterator end() const
{
return End;
}
iterator begin()
{
return start;
}
iterator end()
{
return End;
}
//Capacity
void clear()
{
DeallocateAndDestory();
End = start = end_of_storage = nullptr;
}
bool empty()const
{
return (start == End);
}
const size_type size() const
{
return End - start;
}
const size_type length() const
{
return size();
}
const size_type capacity() const
{
return end_of_storage - start;
}
void resize(size_type n)
{
resize(n, value_type());
}
void resize(size_type n, const value_type &val)
{
if (n <= size())
{
End = start + n;
}
else
{
append(string(n - size(), val));
}
}
void reserve(size_type res_arg = 0)
{
if (res_arg + size() < capacity()) return;
reallocate(res_arg + size());
}
//Modifiers
value_type& operator[](size_type index)
{
if (index < 0 || index >= size())
{
std::cerr << "index out of range!" << std::endl;
std::exit(1);
}
else
{
return *(start + index);
}
}
value_type& front()
{
return *start;
}
value_type& back()
{
auto tmp = end();
return *(--tmp);
}
void push_back(const value_type& val)
{
if (size() == capacity())
reallocate();
*End = val;
End++;
}
void pop_back()
{
if (empty())
{
std::cerr << "Error : pop_back() on empty String!" << std::endl;
exit(1);
}
End--;
}
void swap(string& rhs)
{
std::swap(start, rhs.start);
std::swap(end_of_storage, rhs.end_of_storage);
std::swap(End, rhs.End);
}
void append(const string& rhs)
{
if (rhs.empty()) return;
if (capacity()<size() + rhs.size()) reallocate(size() + rhs.size());
std::copy(rhs.start, rhs.end_of_storage, End);
End += rhs.size();
}
void append(const char* s)
{
if (s == nullptr) return;
size_t cnt = 0;
for (; s[cnt] != ' '; cnt++) {}
if (capacity() < size() + cnt) reallocate(size() + cnt);
std::uninitialized_copy_n(s, cnt, End);
End += cnt;
}
void append(const char* s, size_t l, size_t r)
{
if (r <= l ) return;
if (s == nullptr) return;
if (capacity()<size() + r - l - 1) reallocate(size() + r - l);
std::uninitialized_copy_n(s + l, r - l, End);
End += r - l;
}
string& operator+=(const char c)
{
(*this).push_back(c);
return *this;
}
string& operator+=(const string& rhs)
{
(*this).append(rhs);
return *this;
}
string operator+(const string& rhs)
{
string tmp(*this);
return tmp += rhs;
}
string& operator=(const string& str)
{
return assign(str);
}
string& operator=(const char* s)
{
return assign(string(s));
}
string& operator=(char c)
{
return assign(string((size_type)1, c));
}
string& assign(const string& str)
{
clear();
append(str);
return (*this);
}
string& assign(const char* s)
{
clear();
if (s == nullptr) return *this;
size_t cnt = 0;
while (s[cnt] != ' ') cnt++;
start = data_allocator.allocate(cnt);
End = std::uninitialized_copy_n(s, cnt, start);
end_of_storage += cnt;
}
string& assign(size_type n, char c)
{
clear();
if (n == 0) return *this;
start = data_allocator.allocate(n);
End = end_of_storage = std::uninitialized_fill_n(start, n, c);
}
string& insert(size_type pos, const string& rhs)
{
pos = std::min(size(), pos);
size_type new_size = size() + rhs.size();
iterator new_start = data_allocator.allocate(new_size);
std::copy(start, start + pos, new_start);
std::copy(rhs.start, rhs.End, new_start + pos);
std::copy(start + pos, End, new_start + pos + rhs.size());
start = new_start;
end_of_storage = End = new_size + new_start;
return *this;
}
string& insert(size_type pos, const char* s, size_type n)
{
return insert(pos, string(s, n));
}
string& insert(size_type pos, const char* s)
{
return insert(pos, string(s));
}
iterator insert(iterator pos, const value_type& val)
{
size_type index = pos - start;
if (size() == capacity())
reallocate();
pos = start + index;
if (pos > end()) pos = end();
std::copy(pos, End, pos + 1);
(*pos) = val;
End++;
return pos;
}
string& insert(size_type pos, size_type num, const value_type& val)
{
return insert(pos, string(num, val));
}
string& insert(iterator pos, size_type num, const value_type& val)
{
return insert(pos - start, string(num, val));
}
string& erase(size_type pos, size_type n)
{
std::copy(pos + n + start, End, start + pos);
End = End - n;
return *this;
}
iterator erase(iterator pos)
{
std::copy(pos + 1, End, pos);
End--;
return pos;
}
iterator erase(iterator first, iterator last)
{
std::copy(last, End, first);
End = End - (last - first);
return first;
}
string& replace(size_t pos, size_t n, const string& str)
{
erase(pos, n);
insert(pos, str);
return *this;
}
string& replace(iterator i1, iterator i2, const string& str)
{
insert(erase(i1, i2) - start, str);
return *this;
}
const char* c_str() const
{
if (empty()) return "";
char* ret = new char[End - start + 1];
std::uninitialized_copy(start, End, ret);
ret[End - start] = ' ';
return ret;
}
bool operator == (const string& rhs)
{
if (size() != rhs.size())
return false;
else
{
for (auto i = start, j = rhs.start; i != End; i++, j++)
{
if ((*i) != (*j))
return false;
}
return true;
}
}
bool operator == (const string& rhs) const
{
if (size() != rhs.size())
return false;
else
{
for (auto i = start, j = rhs.start; i != End; i++, j++)
{
if ((*i) != (*j))
return false;
}
return true;
}
}
int compare(const string& rhs)
{
iterator i = start, j = rhs.start;
while (i != End && j != rhs.End)
{
if ((*i) > (*j))
return 1;
else if ((*i) < (*j))
return -1;
else
i++, j++;
}
if (i == End&&j == rhs.End)
return 0;
else if (i == End)
return -1;
else
return 1;
}
size_type copy(char* s, size_type n, size_type pos = 0) const
{
if (pos + n >= size())
{
std::cerr << "out of range" << std::endl;
std::exit(1);
}
std::uninitialized_copy_n(start + pos, n, s);
return n;
}
size_t find(const string& str, size_t pos = 0) const
{
if (size() - pos < str.size())
return (size_type)(-1);
for (auto it = start + pos; it != End; it++)
{
auto i = it, j = str.start;
while (j<str.End && *i == *j)
i++, j++;
if (j == str.End)
return it - start;
}
return (size_type)(-1);
}
size_t find(const char* s, size_t pos, size_t n) const
{
return find(string(s, n), pos);
}
size_t find(const char* s, size_t pos = 0) const
{
return find(string(s), pos);
}
size_t find(char c, size_t pos = 0) const
{
if (empty())
return size_type(-1);
else
{
for (auto it = start; it != End; it++)
if (*it == c)
return it - start;
return size_type(-1);
}
}
string substr(size_t pos = 0, size_t n = 0)
{
return string(start + pos, n);
}
size_t rfind(string& rhs, size_t pos = 0)
{
if (pos == 0) pos = size();
for (auto it = std::min(start + pos, End - 1); it != start - 1; it--)
{
size_t i;
for (i = 0; i < rhs.size();)
if (rhs[i] == *(it + i))
i++;
else
break;
if (i == rhs.size())
return it - start;
}
return size_t(-1);
}
size_t rfind(const char& c, size_t pos = 0)
{
if (pos == 0) pos = size();
for (auto it = std::min(End - 1, start + pos); it != start; it--)
{
if (*it == c)
return it - start;
}
return size_t(-1);
}
size_t rfind(const char* str)
{
return rfind(string(str));
}
size_t find_first_of(const string& rhs, size_t pos = 0)
{
for (auto it = start + pos; it != End; it++)
{
auto i = rhs.start;
while (i != rhs.End)
{
if (*i == *it)
break;
i++;
}
if (i != rhs.End)
return it - start;
}
return (size_t)-1;
}
size_t find_first_of(const char& c, size_t pos = 0)
{
for (auto it = start + pos; it != End; it++)
{
if (*it == c)
return it - start;
}
return (size_t)-1;
}
size_t find_last_of(const char &c, size_t pos = 0)
{
if (pos == 0) pos = size();
for (auto it = pos + start; it != start - 1; it--)
if (*it == c)
return it - start;
return (size_t)-1;
}
size_t find_last_of(const char* str, size_t pos, size_t len)
{
size_t l = 0;
for (size_t i = 0; str[i] != ' '; i++)
l++;
for (auto it = start + pos; it != start + pos - len; it--)
{
size_t i;
for (i = 0; str[i] != ' '; i++)
if (str[i] == *it)
break;
if (str[i] != ' ') return it - start;
}
return size_t(-1);
}
size_t find_last_of(const string& rhs, size_t pos)
{
for (auto it = start + pos; it != start - 1; it--)
{
size_t i = 0;
while (rhs.start + i != rhs.End)
if (*it == *(start + i))
break;
else
i++;
if (rhs.size() != i) return it - start;
}
return size_t(-1);
}
size_t find_first_not_of(const string& rhs)
{
for (auto it = start; it != End; it++)
{
size_t i = 0;
while (i < rhs.size())
if (*(rhs.start + i) == *it)
break;
else
i++;
if (i == rhs.size()) return it - start;
}
return size_t(-1);
}
size_t find_last_not_of(const string& rhs, size_t pos)
{
for (auto it = start + pos; it != start - 1; it--)
{
size_t i = 0;
while (i < rhs.size())
if (*(rhs.start + i) == *it)
break;
else
i++;
if (i == rhs.size()) return it - start;
}
return size_t(-1);
}
bool operator!=(const string& rhs)
{
return !(*this == rhs);
}
bool operator>(const string& rhs)
{
return compare(rhs) > 0;
}
bool operator>=(const string& rhs)
{
return compare(rhs) >= 0;
}
bool operator<(const string& rhs)
{
return compare(rhs) < 0;
}
bool operator<=(const string& rhs)
{
return compare(rhs) <= 0;
}
};
std::ostream& operator<<(std::ostream& os, const ministl::string& rhs)
{
os << rhs.c_str();
return os;
}
size_t hash_value(const string& val)
{
const size_t _FNV_offset_basis = 2166136261U;
const size_t _FNV_prime = 16777619U;
size_t ans = _FNV_offset_basis;
for (auto it = val.begin(); it != val.end(); it++)
{
ans ^= *it;
ans *= _FNV_prime;
}
return ans;
}
}