Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <string>
- #include <iostream>
- /*------------------------- ImmutableString.h -------------------------*/
- #ifndef __IMMUTABLE_STRING_H_INCLUDED__
- #define __IMMUTABLE_STRING_H_INCLUDED__
- #include <iostream>
- #include <cstring>
- #include <cassert>
- #include <memory>
- #if __cplusplus >= 201103L
- # include <type_traits>
- #endif
- namespace System
- {
- template <typename cType>
- struct SHeapArea {
- mutable unsigned m_refcount;
- cType m_string[];
- };
- template <typename cType>
- inline const cType* getEmptyString();
- template <>
- inline const char* getEmptyString<char>() {
- return "";
- }
- template <>
- inline const wchar_t* getEmptyString<wchar_t>() {
- return L"";
- }
- template <typename cType>
- class basic_StringBuilder;
- template <typename cType>
- class basic_String
- {
- #if __cplusplus >= 201103L
- static_assert(std::is_same<cType, char>::value || std::is_same<cType, wchar_t>::value, "The type you've given is currently unsupported");
- #endif
- friend class basic_StringBuilder<cType>;
- private:
- union UData {
- UData(const cType* data): InitializedReadonlyArea(data) {}
- UData(SHeapArea<cType>* data): HeapArea(data) {}
- const cType* InitializedReadonlyArea;
- SHeapArea<cType>* HeapArea;
- } m_data;
- const cType* m_pos;
- size_t m_len, m_capacity;
- public:
- basic_String(): m_data(getEmptyString<cType>()), m_pos(m_data.InitializedReadonlyArea), m_len(size_t()), m_capacity(size_t()) {}
- basic_String(const cType* str, size_t len): m_data(str), m_pos(str), m_len(len), m_capacity(size_t()) {}
- private:
- basic_String(SHeapArea<cType>* data, size_t len, size_t capacity): m_data(data), m_pos(data->m_string), m_len(len), m_capacity(capacity) {}
- public:
- basic_String(const basic_String& rhs): m_data(rhs.m_data), m_pos(rhs.m_pos), m_len(rhs.m_len), m_capacity(rhs.m_capacity) {
- if (m_capacity != 0)
- ++rhs.m_data.HeapArea->m_refcount;
- }
- ~basic_String() {
- if (m_capacity == 0)
- return;
- if (m_data.HeapArea->m_refcount == 1u)
- ::operator delete(m_data.HeapArea);
- else
- --m_data.HeapArea->m_refcount;
- }
- basic_String& operator =(const basic_String& rhs) {
- if (this == &rhs)
- return *this;
- this->~basic_String();
- m_data = rhs.m_data;
- m_pos = rhs.m_pos;
- m_len = rhs.m_len;
- m_capacity = rhs.m_capacity;
- if (m_capacity != 0)
- ++m_data.HeapArea->m_refcount;
- }
- void swap(basic_String& val) {
- std::swap(m_data, val.m_data);
- std::swap(m_pos, val.m_pos);
- std::swap(m_len, val.m_len);
- std::swap(m_capacity, val.m_capacity);
- }
- // FIXME: substr
- //const cType* c_str() const {
- // if (m_capacity != 0)
- // const_cast<cType *>(m_pos)[m_len] = cType('\0');
- // return m_pos;
- //}
- const cType* data() const {
- return m_pos;
- }
- size_t length() const {
- return m_len;
- }
- size_t capacity() const {
- return m_capacity;
- }
- const cType* operator [](size_t index) const {
- assert(index < m_len);
- return m_pos[index];
- }
- basic_String substr(size_t pos = 0, size_t n = npos) const {
- assert(pos < m_len);
- basic_String result(*this);
- result.m_pos += pos;
- result.m_len = (n > m_len || n + pos > m_len) ? m_len - pos : n;
- return result;
- }
- friend std::basic_ostream<cType>& operator <<(std::basic_ostream<cType>& os, const basic_String& rhs) {
- std::copy(rhs.m_pos, rhs.m_pos + rhs.m_len, std::ostreambuf_iterator<cType>(os));
- return os;
- }
- public:
- static const size_t npos = ~0u;
- };
- template <typename cType>
- class basic_StringBuilder
- {
- public:
- basic_StringBuilder(const basic_String<cType>& rhs, size_t size = 0):
- m_len(rhs.m_len), m_capacity((std::max(size, m_len) / newSpaceSize + 1) * newSpaceSize) {
- m_data = (SHeapArea<cType> *)::operator new(sizeof(SHeapArea<cType>) + sizeof(cType) * m_capacity);
- std::memcpy(m_data->m_string, rhs.m_pos, sizeof(cType) * m_len);
- m_data->m_refcount = 1u;
- }
- #if __cplusplus >= 201103L
- basic_StringBuilder(basic_String<cType>&& rhs):
- m_len(rhs.m_len), m_capacity(rhs.m_capacity), m_data(rhs.m_data.HeapArea) {
- assert(rhs.m_capacity != 0 && rhs.m_data.HeapArea->m_refcount == 1);
- rhs.m_data.InitializedReadonlyArea = getEmptyString<cType>();
- rhs.m_pos = rhs.m_data.InitializedReadonlyArea;
- rhs.m_capacity = 0;
- rhs.m_len = 0;
- }
- #endif
- operator basic_String<cType>() {
- return basic_String<cType>(m_data, m_len, m_capacity);
- }
- void reverse(size_t newSize) {
- if (newSize <= m_capacity)
- return;
- newSize = (newSize / newSpaceSize + 1) * newSpaceSize;
- SHeapArea<cType>* newData = (SHeapArea<cType> *)
- ::operator new(sizeof(SHeapArea<cType>) + sizeof(cType) * newSize);
- std::memcpy(newData, m_data, sizeof(SHeapArea<cType>) + sizeof(cType) * m_len);
- ::operator delete(m_data);
- m_capacity = newSize;
- m_data = newData;
- }
- basic_StringBuilder& appendChar(cType c) {
- reverse(m_len + 2);
- m_data->m_string[m_len] = c;
- ++m_len;
- return *this;
- }
- basic_StringBuilder& appendString(const basic_String<cType>& s) {
- reverse(m_len + s.m_len + 1);
- std::memcpy(m_data->m_string + m_len, s.m_pos, s.m_len);
- m_len += s.m_len;
- return *this;
- }
- private:
- static const size_t newSpaceSize = 32;
- size_t m_len, m_capacity;
- SHeapArea<cType>* m_data;
- };
- typedef basic_String<char> String;
- typedef basic_String<wchar_t> wString;
- #if __cplusplus >= 201111L
- String operator "" _ImmStr(const char* str, size_t len)
- {
- return String(str, len);
- }
- wString operator "" _ImmStr(const wchar_t* str, size_t len)
- {
- return wString(str, len);
- }
- #endif
- template <typename cType>
- basic_String<cType> operator +(const basic_String<cType>& lhs, const basic_String<cType>& rhs) {
- return basic_StringBuilder<cType>(lhs, lhs.length() + rhs.length()).appendString(rhs);
- }
- #if __cplusplus >= 201111L
- template <typename cType>
- basic_String<cType> operator +(basic_String<cType>&& lhs, const basic_String<cType>& rhs) {
- return lhs.capacity() != 0
- ? basic_StringBuilder<cType>(std::move(lhs)).appendString(rhs)
- : basic_StringBuilder<cType>(lhs, lhs.length() + rhs.length()).appendString(rhs);
- }
- #endif
- }
- #endif // __IMMUTABLE_STRING_H_INCLUDED__
- /*------------------------- ImmutableString.h -------------------------*/
- int main()
- {
- using namespace std;
- using namespace System;
- String str("Hello world!", 12);
- cout << str << endl;
- cout << String("1234567", 7).substr(3) << endl;
- cout << std::string("1234567").substr(3) << endl;
- cout << (String("1234567", 7) + String("abcdefg", 7) + String("hijkl", 5)).substr(3, 7) << endl;
- cout << (std::string("1234567") + "abcdefg" + "hijkl").substr(3, 7) << endl;
- vector<String> vec;
- vec.push_back(String());
- vec.push_back(String("asxcvbdf", 8).substr(4));
- vec.push_back(String("asxcv", 5) + String("zxcvqwer", 8));
- for (vector<String>::iterator it = vec.begin(); it != vec.end(); ++it)
- cout << *it << endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement