zhangsongcui

Immutable String V2

Jan 1st, 2012
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.49 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstring>
  3. #include <type_traits>
  4. #include <cassert>
  5. #include <memory>
  6.  
  7. template <typename cType>
  8. class basic_ImmutableString
  9. {
  10.     static_assert(std::is_same<cType, char>::value || std::is_same<cType, wchar_t>::value, "The type you've given is currently unsupported");
  11.  
  12. private:
  13.     union UData {
  14.         const cType* const InitializedReadonlyArea;
  15.         struct SHeapArea {
  16.             mutable unsigned m_refcount;
  17.             cType m_string[];
  18.         }* const HeapArea;
  19.  
  20.         UData(const cType* data): InitializedReadonlyArea(data) {}
  21.         UData(SHeapArea* data): HeapArea(data) {}
  22.     } m_data;
  23.     size_t m_len;
  24.     enum { inInitializedReadonlyArea, inHeapArea } m_place;
  25.     const cType* m_pos;
  26.  
  27. public: // Should be privated, but...
  28.     basic_ImmutableString(const cType* str, size_t len): m_data(str), m_len(len), m_place(inInitializedReadonlyArea), m_pos(str) {}
  29.  
  30. private:
  31.     basic_ImmutableString() = delete;
  32.     basic_ImmutableString(typename UData::SHeapArea* data, size_t len): m_data(data), m_len(len), m_place(inHeapArea), m_pos(data->m_string) {}
  33.  
  34. public:
  35.     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) {
  36.         if (m_place == inHeapArea)
  37.             ++rhs.m_data.HeapArea->m_refcount;
  38.     }
  39.  
  40.     ~basic_ImmutableString() {
  41.         if (m_place == inInitializedReadonlyArea)
  42.             return;
  43.         if (m_data.HeapArea->m_refcount == 1u)
  44.             delete m_data.HeapArea;
  45.         else
  46.             --m_data.HeapArea->m_refcount;
  47.     }
  48.  
  49.     basic_ImmutableString& operator =(const basic_ImmutableString& rhs) {
  50.         if (this == &rhs)
  51.             return;
  52.         ~basic_ImmutableString();
  53.         m_data = rhs.m_data;
  54.         m_len = rhs.m_len;
  55.         m_place = rhs.m_place;
  56.         m_pos(rhs.m_pos);
  57.         if (m_place == inHeapArea)
  58.             ++m_data.HeapArea->m_refcount;
  59.     }
  60.  
  61.     // You may not use this function to build a long string, use StringBuilder instead.
  62.     basic_ImmutableString operator +(const basic_ImmutableString& rhs) const {
  63.         auto* heap_data = (typename UData::SHeapArea *)
  64.             ::operator new(sizeof(typename UData::SHeapArea) + sizeof(cType) * (m_len + rhs.m_len));
  65.         heap_data->m_refcount = 1u;
  66.         std::memcpy(heap_data->m_string, m_pos, sizeof(cType) * m_len);
  67.         std::memcpy(heap_data->m_string + m_len, rhs.m_pos, sizeof(cType) * rhs.m_len);
  68.         return basic_ImmutableString(heap_data, m_len + rhs.m_len);
  69.     }
  70.  
  71.     void swap(basic_ImmutableString& val) {
  72.         std::swap(m_len, val.m_len);
  73.         std::swap(m_data, val.m_data);
  74.         std::swap(m_pos, val.m_pos);
  75.         std::swap(m_place, val.m_place);
  76.     }
  77.  
  78.     size_t getLength() const {
  79.         return m_len;
  80.     }
  81.  
  82.     cType operator [](size_t index) const {
  83.         assert(index < m_len);
  84.         return m_pos[index];
  85.     }
  86.  
  87.     basic_ImmutableString substr(size_t pos = 0, size_t n = npos) const {
  88.         assert(pos < m_len);
  89.         basic_ImmutableString result(*this);
  90.         result.m_pos += pos;
  91.         result.m_len = (n > m_len || n + pos > m_len) ? m_len - pos : n;
  92.         return result;
  93.     }
  94.  
  95.     friend std::basic_ostream<cType>& operator <<(std::basic_ostream<cType>& os, const basic_ImmutableString& rhs) {
  96.         std::copy(rhs.m_pos, rhs.m_pos + rhs.m_len, std::ostreambuf_iterator<cType>(os));
  97.         return os;
  98.     }
  99.  
  100. public:
  101.     static const size_t npos = ~0u;
  102. };
  103.  
  104. typedef basic_ImmutableString<char> ImmutableString;
  105. typedef basic_ImmutableString<wchar_t> wImmutableString;
  106.  
  107. ImmutableString operator "" _ImmStr(const char* str, size_t len)
  108. {
  109.     return ImmutableString(str, len);
  110. }
  111.  
  112. wImmutableString operator "" _ImmStr(const wchar_t* str, size_t len)
  113. {
  114.     return wImmutableString(str, len);
  115. }
  116.  
  117. #include <vector>
  118.  
  119. int main()
  120. {
  121.     using namespace std;
  122.     cout << "1234567"_ImmStr.substr(3) << endl;         // Don't need to allocate heap memory
  123.     cout << std::string("1234567").substr(3) << endl;   // May allocate heap memory twice;
  124.     cout << ("1234567"_ImmStr + "abcdefg"_ImmStr).substr(3, 7) << endl; // Only allocate heap memory once
  125.     cout << (std::string("1234567") += "abcdefg").substr(3, 7) << endl; // May allocate heap memory twice or three times
  126.  
  127.     vector<ImmutableString> vec;
  128.     vec.push_back("asxcvbdf"_ImmStr.substr(4));
  129.     vec.push_back("asxcv"_ImmStr + "zxcvqwer"_ImmStr);
  130.     for (auto& str : vec)
  131.         cout << str << endl;
  132. }
Advertisement
Add Comment
Please, Sign In to add comment