Advertisement
zhangsongcui

Immutable String V3.1

Jan 3rd, 2012
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.10 KB | None | 0 0
  1. #include <vector>
  2. #include <string>
  3. #include <iostream>
  4.  
  5. /*-------------------------  ImmutableString.h  -------------------------*/
  6. #ifndef __IMMUTABLE_STRING_H_INCLUDED__
  7. #define __IMMUTABLE_STRING_H_INCLUDED__
  8.  
  9. #include <iostream>
  10. #include <cstring>
  11. #include <cassert>
  12. #include <memory>
  13. #if __cplusplus >= 201103L
  14. #   include <type_traits>
  15. #endif
  16.  
  17. namespace System
  18. {
  19.     template <typename cType>
  20.     struct SHeapArea {
  21.         mutable unsigned m_refcount;
  22.         cType m_string[];
  23.     };
  24.  
  25.     template <typename cType>
  26.     inline const cType* getEmptyString();
  27.  
  28.     template <>
  29.     inline const char* getEmptyString<char>() {
  30.         return "";
  31.     }
  32.  
  33.     template <>
  34.     inline const wchar_t* getEmptyString<wchar_t>() {
  35.         return L"";
  36.     }
  37.  
  38.     template <typename cType>
  39.     class basic_StringBuilder;
  40.  
  41.     template <typename cType>
  42.     class basic_String
  43.     {
  44. #if __cplusplus >= 201103L
  45.         static_assert(std::is_same<cType, char>::value || std::is_same<cType, wchar_t>::value, "The type you've given is currently unsupported");
  46. #endif
  47.         friend class basic_StringBuilder<cType>;
  48.  
  49.     private:
  50.         union UData {
  51.             UData(const cType* data): InitializedReadonlyArea(data) {}
  52.             UData(SHeapArea<cType>* data): HeapArea(data) {}
  53.  
  54.             const cType* InitializedReadonlyArea;
  55.             SHeapArea<cType>* HeapArea;
  56.         } m_data;
  57.         const cType* m_pos;
  58.         size_t m_len, m_capacity;
  59.  
  60.     public:
  61.         basic_String(): m_data(getEmptyString<cType>()), m_pos(m_data.InitializedReadonlyArea), m_len(size_t()), m_capacity(size_t()) {}
  62.         basic_String(const cType* str, size_t len): m_data(str), m_pos(str), m_len(len), m_capacity(size_t()) {}
  63.  
  64.     private:
  65.         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) {}
  66.  
  67.     public:
  68.         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) {
  69.             if (m_capacity != 0)
  70.                 ++rhs.m_data.HeapArea->m_refcount;
  71.         }
  72.  
  73.         ~basic_String() {
  74.             if (m_capacity == 0)
  75.                 return;
  76.             if (m_data.HeapArea->m_refcount == 1u)
  77.                 ::operator delete(m_data.HeapArea);
  78.             else
  79.                 --m_data.HeapArea->m_refcount;
  80.         }
  81.  
  82.         basic_String& operator =(const basic_String& rhs) {
  83.             if (this == &rhs)
  84.                 return *this;
  85.             this->~basic_String();
  86.             m_data = rhs.m_data;
  87.             m_pos = rhs.m_pos;
  88.             m_len = rhs.m_len;
  89.             m_capacity = rhs.m_capacity;
  90.             if (m_capacity != 0)
  91.                 ++m_data.HeapArea->m_refcount;
  92.         }
  93.  
  94.         void swap(basic_String& val) {
  95.             std::swap(m_data, val.m_data);
  96.             std::swap(m_pos, val.m_pos);
  97.             std::swap(m_len, val.m_len);
  98.             std::swap(m_capacity, val.m_capacity);
  99.         }
  100.  
  101.         // FIXME: substr
  102.         //const cType* c_str() const {
  103.         //    if (m_capacity != 0)
  104.         //        const_cast<cType *>(m_pos)[m_len] = cType('\0');
  105.         //    return m_pos;
  106.         //}
  107.  
  108.         const cType* data() const {
  109.             return m_pos;
  110.         }
  111.  
  112.         size_t length() const {
  113.             return m_len;
  114.         }
  115.  
  116.         size_t capacity() const {
  117.             return m_capacity;
  118.         }
  119.  
  120.         const cType* operator [](size_t index) const {
  121.             assert(index < m_len);
  122.             return m_pos[index];
  123.         }
  124.  
  125.         basic_String substr(size_t pos = 0, size_t n = npos) const {
  126.             assert(pos < m_len);
  127.             basic_String result(*this);
  128.             result.m_pos += pos;
  129.             result.m_len = (n > m_len || n + pos > m_len) ? m_len - pos : n;
  130.             return result;
  131.         }
  132.  
  133.         friend std::basic_ostream<cType>& operator <<(std::basic_ostream<cType>& os, const basic_String& rhs) {
  134.             std::copy(rhs.m_pos, rhs.m_pos + rhs.m_len, std::ostreambuf_iterator<cType>(os));
  135.             return os;
  136.         }
  137.  
  138.     public:
  139.         static const size_t npos = ~0u;
  140.     };
  141.  
  142.     template <typename cType>
  143.     class basic_StringBuilder
  144.     {
  145.     public:
  146.         basic_StringBuilder(const basic_String<cType>& rhs, size_t size = 0):
  147.             m_len(rhs.m_len), m_capacity((std::max(size, m_len) / newSpaceSize + 1) * newSpaceSize) {
  148.             m_data = (SHeapArea<cType> *)::operator new(sizeof(SHeapArea<cType>) + sizeof(cType) * m_capacity);
  149.             std::memcpy(m_data->m_string, rhs.m_pos, sizeof(cType) * m_len);
  150.             m_data->m_refcount = 1u;
  151.         }
  152.  
  153. #if __cplusplus >= 201103L
  154.         basic_StringBuilder(basic_String<cType>&& rhs):
  155.             m_len(rhs.m_len), m_capacity(rhs.m_capacity), m_data(rhs.m_data.HeapArea) {
  156.             assert(rhs.m_capacity != 0 && rhs.m_data.HeapArea->m_refcount == 1);
  157.             rhs.m_data.InitializedReadonlyArea = getEmptyString<cType>();
  158.             rhs.m_pos = rhs.m_data.InitializedReadonlyArea;
  159.             rhs.m_capacity = 0;
  160.             rhs.m_len = 0;
  161.         }
  162. #endif
  163.  
  164.         operator basic_String<cType>() {
  165.             return basic_String<cType>(m_data, m_len, m_capacity);
  166.         }
  167.  
  168.         void reverse(size_t newSize) {
  169.             if (newSize <= m_capacity)
  170.                 return;
  171.             newSize = (newSize / newSpaceSize + 1) * newSpaceSize;
  172.             SHeapArea<cType>* newData = (SHeapArea<cType> *)
  173.                 ::operator new(sizeof(SHeapArea<cType>) + sizeof(cType) * newSize);
  174.             std::memcpy(newData, m_data, sizeof(SHeapArea<cType>) + sizeof(cType) * m_len);
  175.             ::operator delete(m_data);
  176.             m_capacity = newSize;
  177.             m_data = newData;
  178.         }
  179.  
  180.         basic_StringBuilder& appendChar(cType c) {
  181.             reverse(m_len + 2);
  182.             m_data->m_string[m_len] = c;
  183.             ++m_len;
  184.             return *this;
  185.         }
  186.  
  187.         basic_StringBuilder& appendString(const basic_String<cType>& s) {
  188.             reverse(m_len + s.m_len + 1);
  189.             std::memcpy(m_data->m_string + m_len, s.m_pos, s.m_len);
  190.             m_len += s.m_len;
  191.             return *this;
  192.         }
  193.  
  194.     private:
  195.         static const size_t newSpaceSize = 32;
  196.         size_t m_len, m_capacity;
  197.         SHeapArea<cType>* m_data;
  198.     };
  199.  
  200.     typedef basic_String<char> String;
  201.     typedef basic_String<wchar_t> wString;
  202.  
  203. #if __cplusplus >= 201111L
  204.     String operator "" _ImmStr(const char* str, size_t len)
  205.     {
  206.         return String(str, len);
  207.     }
  208.  
  209.     wString operator "" _ImmStr(const wchar_t* str, size_t len)
  210.     {
  211.         return wString(str, len);
  212.     }
  213. #endif
  214.  
  215.     template <typename cType>
  216.     basic_String<cType> operator +(const basic_String<cType>& lhs, const basic_String<cType>& rhs) {
  217.         return basic_StringBuilder<cType>(lhs, lhs.length() + rhs.length()).appendString(rhs);
  218.     }
  219.  
  220. #if __cplusplus >= 201111L
  221.     template <typename cType>
  222.     basic_String<cType> operator +(basic_String<cType>&& lhs, const basic_String<cType>& rhs) {
  223.         return lhs.capacity() != 0
  224.             ? basic_StringBuilder<cType>(std::move(lhs)).appendString(rhs)
  225.             : basic_StringBuilder<cType>(lhs, lhs.length() + rhs.length()).appendString(rhs);
  226.     }
  227. #endif
  228. }
  229. #endif // __IMMUTABLE_STRING_H_INCLUDED__
  230. /*-------------------------  ImmutableString.h  -------------------------*/
  231.  
  232. int main()
  233. {
  234.     using namespace std;
  235.     using namespace System;
  236.     String str("Hello world!", 12);
  237.     cout << str << endl;
  238.  
  239.     cout << String("1234567", 7).substr(3) << endl;
  240.     cout << std::string("1234567").substr(3) << endl;
  241.     cout << (String("1234567", 7) + String("abcdefg", 7) + String("hijkl", 5)).substr(3, 7) << endl;
  242.     cout << (std::string("1234567") + "abcdefg" + "hijkl").substr(3, 7) << endl;
  243.  
  244.     vector<String> vec;
  245.     vec.push_back(String());
  246.     vec.push_back(String("asxcvbdf", 8).substr(4));
  247.     vec.push_back(String("asxcv", 5) + String("zxcvqwer", 8));
  248.     for (vector<String>::iterator it = vec.begin(); it != vec.end(); ++it)
  249.         cout << *it << endl;
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement