Usermode/libc++ - system_error and vector implementation
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / include_exp / string
index 7326217..ac9e5f3 100644 (file)
@@ -61,18 +61,9 @@ struct char_traits<wchar_t>
        }
 };
 
-template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
-class basic_string;
-
-typedef basic_string<char>     string;
-
-};     // namespace std
+extern void _throw_out_of_range(const char *message);
 
-#include <stdexcept>
-
-namespace std {
-
-template < class charT, class traits, class Alloc >
+template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
 class basic_string
 {
 public:
@@ -83,16 +74,40 @@ public:
        typedef typename allocator_type::const_reference        const_reference;
        typedef size_t  size_type;
 
+private:
+       struct dynamic_info
+       {
+               allocator_type  m_allocator;
+                int    m_ref_count = 1;
+               size_type       m_capacity = 0;
+               size_type       m_size = 0;
+               typename allocator_type::pointer m_data = 0;
+               dynamic_info(const allocator_type& alloc):
+                       m_allocator(alloc)
+               {
+               }
+               dynamic_info(const dynamic_info& other):
+                       m_allocator(other.m_allocator),
+                       m_ref_count(1),
+                       m_capacity(other.m_capacity),
+                       m_size(other.m_size)
+               {
+                       m_data = m_allocator.allocate(m_capacity);
+                       for( size_type i = 0; i < m_size; i ++ )
+                               m_data[i] = other.m_data[i];
+               }
+       };
+
+public:
        basic_string(const allocator_type& alloc = allocator_type()):
                m_allocator(alloc),
-               m_capacity(0),
-               m_length(0),
-               m_data(0)
+               m_content(0)
        {
        }
-       basic_string(const basic_string& str):
-               basic_string(str, allocator_type())
+       basic_string(const basic_string& str) throw():
+               basic_string(allocator_type())
        {
+               *this = str;
        }
        basic_string(const basic_string& str, const allocator_type& alloc):
                basic_string(str, 0, str.length(), alloc)
@@ -107,8 +122,8 @@ public:
                                len = str.length() - pos;
                        reserve(len);
                        for( size_type i = 0; i < len; i ++ )
-                               m_data[i] = str.m_data[pos+i];
-                       m_length = len;
+                               m_content->m_data[i] = str.m_content->m_data[pos+i];
+                       m_content->m_size = len;
                }
        }
        basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
@@ -122,8 +137,8 @@ public:
                {
                        reserve(n);
                        for( size_type i = 0; i < n; i ++ )
-                               m_data[i] = s[i];
-                       m_length = n;
+                               m_content->m_data[i] = s[i];
+                       m_content->m_size = n;
                }
        }
        basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
@@ -133,16 +148,41 @@ public:
                {
                        reserve(n);
                        for( size_type i = 0; i < n; i ++ )
-                               m_data[i] = c;
-                       m_length = n;
+                               m_content->m_data[i] = c;
+                       m_content->m_size = n;
                }
        }
+       #if __cplusplus < 199711L
+       basic_string(basic_string&& str) noexcept:
+               basic_string(allocator_type())
+       {
+       }
+       basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
+               basic_string(alloc)
+       {
+               m_content = str.m_content;
+               str.m_content = 0;
+       }
+       #endif
+       ~basic_string()
+       {
+               release_content();
+       }
+       basic_string& operator=(const basic_string& str) throw() {
+               return assign(str);
+       }
+       basic_string& operator=(const charT* s) {
+               return assign(s);
+       }
+       basic_string& operator=(charT c) {
+               return assign(c);
+       }
        
        // iterators
        
        // capacity
        size_type size() const {
-               return m_size;
+               return m_content ? m_content->m_size : 0;
        }
        size_type length() const {
                return size();
@@ -152,29 +192,31 @@ public:
        }
        void resize(size_type size, charT c = 0) {
                reserve(size);
-               if( m_size < size ) {
-                       for( size_type ofs = m_size; ofs < size; ofs ++ )
-                               m_data[ofs] = c;
+               if( m_content->m_size < size ) {
+                       for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
+                               m_content->m_data[ofs] = c;
                }
-               m_size = size;
-               m_data[m_size] = 0;
+               m_content->m_size = size;
+               m_content->m_data[size] = 0;
        }
        size_type capacity() const {
-               return m_capacity;
+               return m_content ? m_content->m_capacity : 0;
        }
        void reserve(size_type size) {
+               own_content();
                size = (size+1 + 31) & ~31;
-               if( size > m_capacity ) {
+               if( size > m_content->m_capacity ) {
                        auto new_area = m_allocator.allocate(size);
-                       for( size_type i = 0; i < m_length; i ++ )
-                               new_area[i] = m_data[i];
-                       m_allocator.deallocate(m_data, m_capacity);
-                       m_data = new_area;
-                       m_capacity = size;
+                       for( size_type i = 0; i < m_content->m_size; i ++ )
+                               new_area[i] = m_content->m_data[i];
+                       m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
+                       m_content->m_data = new_area;
+                       m_content->m_capacity = size;
                }
        }
        void clear() {
-               m_size = 0;
+               own_content();
+               m_content->m_size = 0;
        }
        bool empty() const {
                return length() == 0;
@@ -182,37 +224,197 @@ public:
        
        // Access
        reference operator[] (size_type pos) {
-               return m_data[pos];
+               own_content();
+               return m_content->m_data[pos];
        }
        const_reference operator[] (size_type pos) const {
-               return m_data[pos];
+               return (m_content ? m_content->m_data[pos] : *(const charT*)0);
        }
        reference at(size_type pos) {
-               if(pos >= m_size)       throw ::std::out_of_range("basic_string - at");
-               return m_data[pos];
+               own_content();
+               if(pos >= m_content->m_size)
+                       _throw_out_of_range("basic_string - at");
+               return m_content->m_data[pos];
        }
        const_reference at(size_type pos) const {
-               if(pos >= m_size)       throw ::std::out_of_range("basic_string - at");
-               return m_data[pos];
+               if(!m_content || pos >= m_content.m_size)
+                       _throw_out_of_range("basic_string - at");
+               return m_content->m_data[pos];
        }
        
        // Modifiers
-       basic_string& operator +=(const basic_string& str);
-       basic_string& operator +=(const charT* s);
-       basic_string& operator +=(charT c);
+       basic_string& operator +=(const basic_string& str) {
+               return append(str);
+       }
+       basic_string& operator +=(const charT* s) {
+               return append(s);
+       }
+       basic_string& operator +=(charT c) {
+               push_back(c);
+               return *this;
+       }
+       basic_string& append(const basic_string& str) {
+               return append(str, 0, npos);
+       }
+       basic_string& append(const basic_string& str, size_type subpos, size_type sublen) {
+               if(subpos >= str.size())
+                       _throw_out_of_range("basic_string - assign source");
+               if( sublen > str.size() - subpos )
+                       sublen = str.size() - subpos;
+               append( str.data() + subpos, sublen );
+               return *this;
+       }
+       basic_string& append(const charT* s) {
+               return append(s, traits::length(s));
+       }
+       basic_string& append(const charT* s, size_type n) {
+               reserve(size() + n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[size() + i] = s[i];
+               m_content->m_data[size()+n] = '\0';
+               m_content->m_size += n;
+               return *this;
+       }
+       basic_string& append(size_type n, charT c) {
+               reserve(size() + n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[size() + i] = c;
+               m_content->m_data[size()+n] = '\0';
+               m_content->m_size += n;
+               return *this;
+       }
+       void push_back(charT c) {
+               append(1, c);
+       }
+       basic_string& assign(const basic_string& str) throw() {
+               // Special case, triggers copy-on-write.
+               release_content();
+               m_content = str.m_content;
+               m_content->m_ref_count ++;
+               return *this;
+       }
+       basic_string& assign(const basic_string& str, size_type subpos, size_type sublen) {
+               if(subpos >= str.size())
+                       _throw_out_of_range("basic_string - assign source");
+               if( sublen > str.size() - subpos )
+                       sublen = str.size() - subpos;
+               
+               return assign(str.data() + subpos, sublen);
+       }
+       basic_string& assign(const charT* s) {
+               return assign(s, traits::length(s));
+       }
+       basic_string& assign(const charT* s, size_type n) {
+               release_content();
+               reserve(n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[i] = s[i];
+               m_content->m_data[n] = '\0';
+               m_content->m_size = n;
+               return *this;
+       }
+       basic_string& assign(size_type n, charT c) {
+               release_content();
+               reserve(n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[i] = c;
+               m_content->m_data[n] = '\0';
+               m_content->m_size = n;
+               return *this;
+       }
+       
+       // String operations
+       const char *c_str() const {
+               // TODO: this is const, but also might need to do processing
+               return (m_content ? m_content->m_data : "");
+       }
+       const char *data() const {
+               return (m_content ? m_content->m_data : NULL);
+       }
        
        static const size_type npos = -1;
 private:
        allocator_type  m_allocator;
-       size_type       m_capacity;
-       size_type       m_size;
-       size_type       m_length;
-       typename allocator_type::pointer m_data;
-};
+       dynamic_info    *m_content;
 
+       void own_content() {
+               if(!m_content)
+               {
+                       m_content = new dynamic_info(m_allocator);
+               }
+               else if( m_content->m_ref_count > 1 )
+               {
+                       dynamic_info *new_cont = new dynamic_info(*m_content);
+                       m_content->m_ref_count --;
+                       m_content = new_cont;
+               }
+               else
+               {
+                       // already owned
+               }
+       }
+       void release_content() {
+               if( m_content )
+               {
+                       m_content->m_ref_count --;
+                       if( m_content->m_ref_count == 0 ) {
+                               m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
+                               delete m_content;
+                       }
+                       m_content = NULL;
+               }
+       }
 };
 
-#include <stdexcept>
+typedef basic_string<char>     string;
+
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT* rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + traits::length(rhs));
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const charT* lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(traits::length(lhs) + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + 1);
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const charT lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(1 + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+
+};
 
 #endif
 

UCC git Repository :: git.ucc.asn.au