Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstring>
- #include <type_traits>
- #include <cassert>
- #include <memory>
- template <typename cType>
- class basic_ImmutableString
- {
- static_assert(std::is_same<cType, char>::value || std::is_same<cType, wchar_t>::value, "The type you've given is currently unsupported");
- private:
- union UData {
- const cType* const InitializedReadonlyArea;
- struct SHeapArea {
- mutable unsigned m_refcount;
- cType m_string[];
- }* const HeapArea;
- UData(const cType* data): InitializedReadonlyArea(data) {}
- UData(SHeapArea* data): HeapArea(data) {}
- } m_data;
- size_t m_len;
- enum { inInitializedReadonlyArea, inHeapArea } m_place;
- const cType* m_pos;
- public: // Should be privated, but...
- basic_ImmutableString(const cType* str, size_t len): m_data(str), m_len(len), m_place(inInitializedReadonlyArea), m_pos(str) {}
- private:
- basic_ImmutableString() = delete;
- basic_ImmutableString(typename UData::SHeapArea* data, size_t len): m_data(data), m_len(len), m_place(inHeapArea), m_pos(data->m_string) {}
- public:
- basic_ImmutableString(const basic_ImmutableString& rhs): m_data(rhs.m_data), m_len(rhs.m_len), m_place(rhs.m_place), m_pos(rhs.m_pos) {
- if (m_place == inHeapArea)
- ++rhs.m_data.HeapArea->m_refcount;
- }
- ~basic_ImmutableString() {
- if (m_place == inInitializedReadonlyArea)
- return;
- if (m_data.HeapArea->m_refcount == 1u)
- delete m_data.HeapArea;
- else
- --m_data.HeapArea->m_refcount;
- }
- basic_ImmutableString& operator =(const basic_ImmutableString& rhs) {
- if (this == &rhs)
- return;
- ~basic_ImmutableString();
- m_data = rhs.m_data;
- m_len = rhs.m_len;
- m_place = rhs.m_place;
- m_pos(rhs.m_pos);
- if (m_place == inHeapArea)
- ++m_data.HeapArea->m_refcount;
- }
- // You may not use this function to build a long string, use StringBuilder instead.
- basic_ImmutableString operator +(const basic_ImmutableString& rhs) const {
- auto* heap_data = (typename UData::SHeapArea *)
- ::operator new(sizeof(typename UData::SHeapArea) + sizeof(cType) * (m_len + rhs.m_len));
- heap_data->m_refcount = 1u;
- std::memcpy(heap_data->m_string, m_pos, sizeof(cType) * m_len);
- std::memcpy(heap_data->m_string + m_len, rhs.m_pos, sizeof(cType) * rhs.m_len);
- return basic_ImmutableString(heap_data, m_len + rhs.m_len);
- }
- void swap(basic_ImmutableString& val) {
- std::swap(m_len, val.m_len);
- std::swap(m_data, val.m_data);
- std::swap(m_pos, val.m_pos);
- std::swap(m_place, val.m_place);
- }
- size_t getLength() const {
- return m_len;
- }
- cType operator [](size_t index) const {
- assert(index < m_len);
- return m_pos[index];
- }
- basic_ImmutableString substr(size_t pos = 0, size_t n = npos) const {
- assert(pos < m_len);
- basic_ImmutableString 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_ImmutableString& 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;
- };
- typedef basic_ImmutableString<char> ImmutableString;
- typedef basic_ImmutableString<wchar_t> wImmutableString;
- ImmutableString operator "" _ImmStr(const char* str, size_t len)
- {
- return ImmutableString(str, len);
- }
- wImmutableString operator "" _ImmStr(const wchar_t* str, size_t len)
- {
- return wImmutableString(str, len);
- }
- #include <vector>
- int main()
- {
- using namespace std;
- cout << "1234567"_ImmStr.substr(3) << endl; // Don't need to allocate heap memory
- cout << std::string("1234567").substr(3) << endl; // May allocate heap memory twice;
- cout << ("1234567"_ImmStr + "abcdefg"_ImmStr).substr(3, 7) << endl; // Only allocate heap memory once
- cout << (std::string("1234567") += "abcdefg").substr(3, 7) << endl; // May allocate heap memory twice or three times
- vector<ImmutableString> vec;
- vec.push_back("asxcvbdf"_ImmStr.substr(4));
- vec.push_back("asxcv"_ImmStr + "zxcvqwer"_ImmStr);
- for (auto& str : vec)
- cout << str << endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment