Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / include_exp / string
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/string b/Usermode/Libraries/libc++.so_src/include_exp/string
new file mode 100644 (file)
index 0000000..f36077d
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * string (header)
+ * - C++'s String type
+ */
+#ifndef _LIBCXX_STRING_
+#define _LIBCXX_STRING_
+
+#include "_libcxx_helpers.h"
+#include <allocator>
+#include <initializer_list>
+
+namespace std {
+
+template <class charT>
+struct char_traits
+{
+};
+
+template <>
+struct char_traits<char>
+{
+       typedef char    char_type;
+       typedef int     int_type;
+       //typedef streamoff     off_type;
+       //typedef streampos     pos_type;
+       //typedef mbstate_t     state_type;
+       
+       static bool eq(const char_type& c, const char_type& d) {
+               return c == d;
+       }
+       static bool lt(const char_type& c, const char_type& d) {
+               return c < d;
+       }
+       static size_t length(const char_type* s) {
+               size_t  ret = 0;
+               while(*s++)     ret ++;
+               return ret;
+       }
+       static int compare (const char_type* p, const char_type* q, size_t n) {
+               while (n--) {
+                       if( !eq(*p,*q) )
+                               return lt(*p,*q) ? -1 : 1;
+                       ++p; ++q;
+               }
+               return 0;
+       }
+};
+
+template <>
+struct char_traits<wchar_t>
+{
+       typedef wchar_t char_type;
+       typedef int     int_type;
+       //typedef streamoff     off_type;
+       //typedef streampos     pos_type;
+       //typedef mbstate_t     state_type;
+       
+       static size_t length(const char_type* s) {
+               size_t  ret = 0;
+               while(*s++)     ret ++;
+               return ret;
+       }
+       static bool eq(const char_type& c, const char_type& d) {
+               return c == d;
+       }
+       static bool lt(const char_type& c, const char_type& d) {
+               return c < d;
+       }
+};
+
+extern void _throw_out_of_range(const char *message);
+
+template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
+class basic_string
+{
+public:
+       typedef traits  traits_type;
+       typedef Alloc   allocator_type;
+       typedef charT   value_type;
+       typedef typename allocator_type::reference      reference;
+       typedef typename allocator_type::const_reference        const_reference;
+       typedef size_t  size_type;
+       
+       typedef charT*  iterator;
+       typedef const charT*    const_iterator;
+
+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];
+               }
+       };
+
+       allocator_type  m_allocator;
+       dynamic_info    *m_content;
+
+public:
+       basic_string(const allocator_type& alloc = allocator_type()):
+               m_allocator(alloc),
+               m_content(0)
+       {
+       }
+       basic_string(const basic_string& str) throw():
+               basic_string(allocator_type())
+       {
+               *this = str;
+       }
+       #if _CXX11_AVAIL
+       basic_string(basic_string&& str):
+               m_allocator(str.m_allocator),
+               m_content(str.m_content)
+       {
+               str.m_content = 0;
+               ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
+       }
+       #endif
+       basic_string(const basic_string& str, const allocator_type& alloc):
+               basic_string(str, 0, str.length(), alloc)
+       {
+       }
+       basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( pos < str.length() )
+               {
+                       if( len > str.length() - pos )
+                               len = str.length() - pos;
+                       reserve(len);
+                       for( size_type i = 0; i < len; i ++ )
+                               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()):
+               basic_string(s, traits::length(s), alloc)
+       {
+       }
+       basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( n > 0 )
+               {
+                       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;
+               }
+       }
+       basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( n > 0 )
+               {
+                       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;
+               }
+       }
+       #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_content ? m_content->m_size : 0;
+       }
+       size_type length() const {
+               return size();
+       }
+       size_type max_size() const {
+               return -1;
+       }
+       void resize(size_type size, charT c = 0) {
+               reserve(size);
+               if( m_content->m_size < size ) {
+                       for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
+                               m_content->m_data[ofs] = c;
+                       m_content->m_data[size] = 0;
+               }
+               m_content->m_size = size;
+               m_content->m_data[size] = 0;
+       }
+       size_type capacity() const {
+               return m_content ? m_content->m_capacity : 0;
+       }
+       void reserve(size_type size) {
+               own_content();
+               size = (size+1 + 31) & ~31;
+               if( size > m_content->m_capacity ) {
+                       auto new_area = m_allocator.allocate(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() {
+               own_content();
+               m_content->m_size = 0;
+       }
+       bool empty() const {
+               return length() == 0;
+       }
+       #if _CXX11_AVAIL
+       void shrink_to_fit();
+       #endif
+       
+       // Access
+       reference operator[] (size_type pos) {
+               own_content();
+               return m_content->m_data[pos];
+       }
+       const_reference operator[] (size_type pos) const {
+               return (m_content ? m_content->m_data[pos] : *(const charT*)0);
+       }
+       reference at(size_type 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(!m_content || pos >= m_content.m_size)
+                       _throw_out_of_range("basic_string - at");
+               return m_content->m_data[pos];
+       }
+       #if _CXX11_AVAIL
+       reference back() {
+               own_content();
+               return m_content->m_data[m_content->m_size];
+       }
+       const_reference back() const {
+               return m_content->m_data[m_content->m_size];
+       }
+       reference front() {
+               own_content();
+               return m_content->m_data[0];
+       }
+       const_reference front() const {
+               return m_content->m_data[0];
+       }
+       #endif
+       
+       // Modifiers
+       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;
+       }
+       
+       basic_string& insert(size_type pos, const basic_string& str);
+       basic_string& insert(size_type pos, const basic_string& str, size_type subpos, size_type sublen);
+       basic_string& insert(size_type pos, const charT& s);
+       basic_string& insert(size_type pos, const charT& s, size_type n);
+       basic_string& insert(size_type pos, size_type n, charT c);
+       iterator insert(const_iterator p, size_type n, charT c);
+       iterator insert(const_iterator p, charT c);
+       template <class InputIterator>
+       iterator insert(iterator p, InputIterator first, InputIterator last);
+       #if _CXX11_AVAIL
+       basic_string& insert(const_iterator p, initializer_list<charT> il);
+       #endif
+       
+       basic_string& erase(size_type pos = 0, size_type len = npos);
+       iterator erase(const_iterator p);
+       iterator erase(const_iterator first, const_iterator last);
+       
+       basic_string& replace(size_type pos, size_type len, const basic_string& str);
+       basic_string& replace(const_iterator i1, const_reference i2, const basic_string& str);
+       basic_string& replace(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen);
+       basic_string& replace(size_type pos, size_type len, const charT *s);
+       basic_string& replace(const_iterator i1, const_reference i2, const charT* s);
+       basic_string& replace(size_type pos, size_type len, const charT *s, size_type n);
+       basic_string& replace(const_iterator i1, const_reference i2, const charT* s, size_type n);
+       basic_string& replace(size_type pos, size_type len, size_type n, charT c);
+       basic_string& replace(const_iterator i1, const_reference i2, size_type n, charT c);
+       template <class InputIterator>
+       basic_string& replace(const_iterator i1, const_reference i2, InputIterator first, InputIterator last);
+       basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
+       
+       void swap(basic_string& str)
+       {
+               auto tmp = m_content;
+               m_content = str.m_content;
+               str.m_content = tmp;
+       }
+       
+       #if _CXX11_AVAIL
+       void pop_back();
+       #endif
+       
+       // String operations
+       const charT *c_str() const noexcept
+       {
+               // TODO: this is const, but also might need to do processing
+               if(m_content) {
+                       _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
+               }
+               return (m_content ? m_content->m_data : "");
+       }
+       const charT *data() const
+       {
+               return (m_content ? m_content->m_data : NULL);
+       }
+       allocator_type get_allocator() const noexcept
+       {
+               return m_allocator;
+       }
+       size_type copy(charT* s, size_type len, size_type pos = 0) const;
+       
+       size_type find(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find(const charT* s, size_type pos = 0) const;
+       size_type find(const charT* s, size_type pos, size_type n) const;
+       size_type find(charT c, size_type pos = 0) const noexcept;
+       
+       size_type rfind(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type rfind(const charT* s, size_type pos = 0) const;
+       size_type rfind(const charT* s, size_type pos, size_type n) const;
+       size_type rfind(charT c, size_type pos = 0) const noexcept;
+       
+       size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_first_of(const charT* s, size_type pos = 0) const;
+       size_type find_first_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_first_of(charT c, size_type pos = 0) const noexcept;
+       
+       size_type find_last_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_last_of(const charT* s, size_type pos = 0) const;
+       size_type find_last_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_last_of(charT c, size_type pos = 0) const noexcept;
+
+       size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_first_not_of(const charT* s, size_type pos = 0) const;
+       size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
+
+       size_type find_last_not_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_last_not_of(const charT* s, size_type pos = 0) const;
+       size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_last_not_of(charT c, size_type pos = 0) const noexcept;
+
+       basic_string substr(size_type pos = 0, size_type len = npos) const;
+       
+       int compare(const basic_string& str) const noexcept {
+               return compare(0, size(), str.data(), str.size());
+       }
+       int compare(size_type pos, size_type len, const basic_string& str) const {
+               _libcxx_assert(pos <= size());
+               _libcxx_assert(len <= size());
+               _libcxx_assert(pos+len <= size());
+               return compare(pos, len, str.data(), str.size());
+       }
+       int compare(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen) const {
+               // TODO: check
+               _libcxx_assert(subpos <= str.size());
+               _libcxx_assert(sublen <= str.size());
+               _libcxx_assert(subpos+sublen <= str.size());
+               return compare(pos, len, str.data()+subpos, sublen);
+       }
+       int compare(const charT* s) const {
+               return compare(0, npos, s, traits::length(s));
+       }
+       int compare(size_type pos, size_type len, const charT* s) const {
+               return compare(pos, len, s, traits::length(s));
+       }
+       int compare(size_type pos, size_type len, const charT* s, size_type n) const {
+               if( n <= len ) {
+                       int rv = traits::compare(data()+pos, s, n);
+                       if( rv == 0 && n < len ) {
+                               rv = -1;
+                       }
+                       return rv;
+               }
+               else {
+                       int rv = traits::compare(data()+pos, s, len);
+                       if(rv == 0) {
+                               rv = 1;
+                       }
+                       return rv;
+               }
+       }
+       
+       static const size_type npos = -1;
+private:
+       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;
+               }
+       }
+};
+
+typedef basic_string<char>     string;
+
+#define _libcxx_str    basic_string<charT,traits,Alloc>
+
+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;
+}
+
+// Three overloads each
+// name: Actual operator, opp: reversed operator
+#define _libcxx_string_def_cmp(name, opp) \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const _libcxx_str& lhs, const _libcxx_str& rhs) { return lhs.compare(rhs) name 0; } \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const charT* lhs, const _libcxx_str& rhs) { return rhs.compare(lhs) opp 0; } \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const _libcxx_str& lhs, const charT* rhs) { return lhs.compare(rhs) name 0; }
+
+_libcxx_string_def_cmp(<, >)
+_libcxx_string_def_cmp(<=, >=)
+_libcxx_string_def_cmp(==, ==)
+_libcxx_string_def_cmp(>=, <=)
+_libcxx_string_def_cmp(>, <)
+};
+
+#endif
+
+// vim: ft=cpp

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