/* Copyright (C) 2004 Garrett A. Kajmowicz This file is part of the uClibc++ Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #ifdef __UCLIBCXX_HAS_WCHAR__ #include #include #endif #ifndef __HEADER_STD_STRING #define __HEADER_STD_STRING 1 namespace std{ //Basic basic_string template, class A = allocator > class basic_string; typedef basic_string string; #ifdef __UCLIBCXX_HAS_WCHAR__ typedef basic_string wstring; #endif //template, class A = allocator > class _UCXXEXPORT basic_string template class basic_string : public std::vector { public: typedef Tr traits_type; typedef typename Tr::char_type value_type; typedef A allocator_type; typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef typename A::reference reference; typedef typename A::const_reference const_reference; typedef typename A::pointer pointer; typedef typename A::const_pointer const_pointer; typedef typename vector::iterator iterator; typedef typename vector::const_iterator const_iterator; typedef typename vector::reverse_iterator reverse_iterator; typedef typename vector::const_reverse_iterator const_reverse_iterator; static const size_type npos = (size_type)-1; explicit _UCXXEXPORT basic_string(const A& al = A()) : vector(al){ return; } _UCXXEXPORT basic_string(const basic_string& str, size_type pos = 0, size_type n = npos, const A& al = A()); //Below _UCXXEXPORT basic_string(const Ch* s, size_type n, const A& al = A()) : vector(al) { if(n == npos){ __throw_out_of_range(); } if(s > (void *)0){ resize(n); Tr::copy(vector::data, s, vector::elements); } } _UCXXEXPORT basic_string(const Ch* s, const A& al = A()); //Below _UCXXEXPORT basic_string(size_type n, Ch c, const A& al = A()) : vector(n, c, al) { } template _UCXXEXPORT basic_string(InputIterator begin, InputIterator end, const A& a = A()) :vector(begin, end) { } _UCXXEXPORT ~basic_string() { return; } _UCXXEXPORT basic_string& operator=(const basic_string& str); //Below _UCXXEXPORT basic_string& operator=(const Ch* s){ vector::clear(); if(s!=0){ size_type len = Tr::length(s); resize(len); Tr::copy( vector::data, s, len); } return *this; } _UCXXEXPORT basic_string& operator=(Ch c){ vector::clear(); vector::push_back(c); return *this; } inline _UCXXEXPORT size_type length() const { return vector::size(); } void _UCXXEXPORT resize(size_type n, Ch c = Ch()){ vector::resize(n, c); } _UCXXEXPORT basic_string& operator+=(const basic_string& str){ return append(str); } _UCXXEXPORT basic_string& operator+=(const Ch * s){ return append(s); } _UCXXEXPORT basic_string& operator+=(Ch c){ vector::push_back(c); return *this; } _UCXXEXPORT basic_string& append(const basic_string& str){ size_t temp = vector::elements; resize(vector::elements + str.elements); Tr::copy( vector::data + temp, str.vector::data, str.elements); return *this; } _UCXXEXPORT basic_string& append(const basic_string& str, size_type pos, size_type n){ if(pos > str.size()){ __throw_out_of_range(); } size_type rlen = str.elements - pos; if(rlen > n){ rlen = n; } if(vector::elements > npos - rlen){ __throw_length_error(); } size_t temp = vector::elements; resize(vector::elements + rlen); Tr::copy( vector::data + temp, str.vector::data + pos, rlen); return *this; } _UCXXEXPORT basic_string& append(const Ch* s, size_type n){ size_t temp = vector::elements; resize(vector::elements + n); Tr::copy( vector::data + temp, s, n); return *this; } _UCXXEXPORT basic_string& append(const Ch* s){ size_type strLen = Tr::length(s); size_t temp = vector::elements; resize(vector::elements + strLen); Tr::copy( vector::data + temp, s, strLen); return *this; } _UCXXEXPORT basic_string& append(size_type n, Ch c){ vector::resize(vector::elements + n, c); return *this; } _UCXXEXPORT basic_string& assign(const basic_string& str){ operator=(str); return *this; } _UCXXEXPORT basic_string& assign(const basic_string& str, size_type pos, size_type n){ if(pos > str.elements){ __throw_out_of_range(); } size_type r = str.elements - pos; if(r > n){ r = n; } resize(r); Tr::copy(vector::data, str.vector::data + pos, r); return *this; } _UCXXEXPORT basic_string& assign(const Ch* s, size_type n){ resize(n); Tr::copy(vector::data, s, n); return *this; } _UCXXEXPORT basic_string& assign(const Ch* s){ size_type len = Tr::length(s); return assign(s, len); } _UCXXEXPORT basic_string& assign(size_type n, Ch c){ vector::clear(); vector::resize(n, Ch() ); return *this; } template _UCXXEXPORT basic_string& assign(InputIterator first, InputIterator last){ vector::resize(0, Ch()); while (first != last){ append(*first); ++first; } return *this; } _UCXXEXPORT basic_string& insert(size_type pos1, const basic_string& str, size_type pos2=0, size_type n=npos){ if(pos1 > vector::elements || pos2 > str.elements){ __throw_out_of_range(); } size_type r = str.elements - pos2; if( r > n){ r = n; } if(vector::elements > npos - r){ __throw_length_error(); } size_type temp = vector::elements; resize(vector::elements + r); Tr::move(vector::data + pos1 + r, vector::data + pos1, temp - pos1); Tr::copy(vector::data + pos1, str.vector::data + pos2, r); return *this; } _UCXXEXPORT basic_string& insert(size_type pos, const Ch* s, size_type n){ if(pos > vector::elements){ __throw_out_of_range(); } if(vector::elements > npos - n){ __throw_length_error(); } size_type temp = vector::elements; resize(vector::elements + n); Tr::move(vector::data + pos + n, vector::data + pos, temp - pos); Tr::copy(vector::data + pos, s, n); return *this; } inline _UCXXEXPORT basic_string& insert(size_type pos, const Ch* s){ size_type len = Tr::length(s); return insert(pos, s, len); } _UCXXEXPORT basic_string& insert(size_type pos, size_type n, Ch c){ if(pos > vector::elements){ __throw_out_of_range(); } if(vector::elements > npos - n){ __throw_length_error(); } size_type temp = vector::elements; resize(vector::elements + n); Tr::move(vector::data + pos + n, vector::data + pos, temp - pos); Tr::assign(vector::data + pos, n, c); return *this; } // iterator insert(iterator p, charT c = charT()); // void insert(iterator p, size_type n, charT c); // template void insert(iterator p, InputIterator first, InputIterator last); _UCXXEXPORT basic_string& erase(size_type pos = 0, size_type n = npos){ size_type xlen = vector::elements - pos; if(xlen > n){ xlen = n; } size_type temp = vector::elements; Tr::move(vector::data + pos, vector::data + pos + xlen, temp - pos - xlen); resize(temp - xlen); return *this; } _UCXXEXPORT iterator erase(iterator position){ if(position == vector::end()){ return position; } ++position; iterator temp = position; while(position != vector::end()){ *(position-1) = *position; ++position; } vector::pop_back(); return temp; } _UCXXEXPORT iterator erase(iterator first, iterator last){ size_t count = last - first; iterator temp = last; while(last != vector::end()){ *(last - count) = *last; ++last; } resize( vector::elements-count); return temp; } _UCXXEXPORT basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2=0, size_type n2=npos) { if(pos1 > vector::elements){ __throw_out_of_range(); } size_type xlen = vector::elements - pos1; if(xlen > n1){ xlen = n1; } size_type rlen = str.elements - pos2; if(rlen > n2){ rlen = n2; } if((vector::elements - xlen) >= (npos - rlen)){ __throw_length_error(); } size_t temp = vector::elements; if(rlen > xlen){ //Only if making larger resize(temp - xlen + rlen); } //Final length = vector::elements - xlen + rlen //Initial block is of size pos1 //Block 2 is of size len Tr::move(vector::data + pos1 + rlen, vector::data + pos1 + xlen, temp - pos1 - xlen); Tr::copy(vector::data + pos1, str.vector::data + pos2, rlen); resize(temp - xlen + rlen); return *this; } _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, const Ch* s, size_type n2){ return replace(pos,n1,basic_string(s,n2)); } inline _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, const Ch* s){ return replace(pos,n1,basic_string(s)); } _UCXXEXPORT basic_string& replace(size_type pos, size_type n1, size_type n2, Ch c){ return replace(pos,n1,basic_string(n2,c)); } // _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const basic_string& str); // _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const Ch* s, size_type n); // _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, const Ch* s); // _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, size_type n, Ch c); /* template _UCXXEXPORT basic_string& replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2);*/ size_type _UCXXEXPORT copy(Ch* s, size_type n, size_type pos = 0) const{ if(pos > vector::elements){ __throw_out_of_range(); } size_type r = vector::elements - pos; if(r > n){ r = n; } Tr::copy(s, vector::data + pos, r); return r; } _UCXXEXPORT void swap(basic_string& s){ //Data pointers vector::swap(s); } _UCXXEXPORT const Ch* c_str() const{ const_cast *>(this)->reserve(vector::elements+1); vector::data[vector::elements] = 0; //Add 0 at the end return vector::data; } _UCXXEXPORT const Ch* data() const{ return vector::data; } _UCXXEXPORT allocator_type get_allocator() const{ return vector::a; } _UCXXEXPORT size_type find (const basic_string& str, size_type pos = 0) const; //Below _UCXXEXPORT size_type find (const Ch* s, size_type pos, size_type n) const{ return find(basic_string(s,n), pos); } _UCXXEXPORT size_type find (const Ch* s, size_type pos = 0) const{ return find(basic_string(s), pos); } _UCXXEXPORT size_type find (Ch c, size_type pos = 0) const{ for(size_type i = pos; i < length(); ++i){ if(this->operator[](i) == c){ return i; } } return npos; } _UCXXEXPORT size_type rfind(const basic_string& str, size_type pos = npos) const{ if(pos >= length()){ pos = length(); } for(size_type i = pos; i > 0; --i){ if(str == substr(i-1, str.length())){ return i-1; } } return npos; } _UCXXEXPORT size_type rfind(const Ch* s, size_type pos, size_type n) const{ return rfind(basic_string(s,n),pos); } _UCXXEXPORT size_type rfind(const Ch* s, size_type pos = npos) const{ return rfind(basic_string(s),pos); } _UCXXEXPORT size_type rfind(Ch c, size_type pos = npos) const{ return rfind(basic_string(1,c),pos); } _UCXXEXPORT size_type find_first_of(const basic_string& str, size_type pos = 0) const{ for(size_type i = pos; i < length(); ++i){ for(size_type j = 0; j < str.length() ; ++j){ if( Tr::eq(str[j], this->operator[](i)) ){ return i; } } } return npos; } _UCXXEXPORT size_type find_first_of(const Ch* s, size_type pos, size_type n) const{ return find_first_of(basic_string(s,n),pos); } _UCXXEXPORT size_type find_first_of(const Ch* s, size_type pos = 0) const{ return find_first_of(basic_string(s),pos); } _UCXXEXPORT size_type find_first_of(Ch c, size_type pos = 0) const{ for(size_type i = pos; i< length(); ++i){ if( Tr::eq(this->operator[](i), c) ){ return i; } } return npos; } _UCXXEXPORT size_type find_last_of (const basic_string& str, size_type pos = npos) const{ if(pos > length()){ pos = length(); } for(size_type i = pos; i >0 ; --i){ for(size_type j = 0 ; j < str.length(); ++j){ if( Tr::eq(this->operator[](i-1), str[j]) ){ return i-1; } } } return npos; } _UCXXEXPORT size_type find_last_of (const Ch* s, size_type pos, size_type n) const{ return find_last_of(basic_string(s,n),pos); } _UCXXEXPORT size_type find_last_of (const Ch* s, size_type pos = npos) const{ return find_last_of(basic_string(s),pos); } _UCXXEXPORT size_type find_last_of (Ch c, size_type pos = npos) const{ if(pos > length()){ pos = length(); } for(size_type i = pos; i >0 ; --i){ if( Tr::eq(this->operator[](i-1), c) ){ return i-1; } } return npos; } _UCXXEXPORT size_type find_first_not_of(const basic_string& str, size_type pos = 0) const{ bool foundCharacter; for(size_type i = pos; i < length(); ++i){ foundCharacter = false; for(size_type j = 0; j < str.length() ; ++j){ if( Tr::eq(str[j], this->operator[](i)) ){ foundCharacter = true; } } if(foundCharacter == false){ return i; } } return npos; } _UCXXEXPORT size_type find_first_not_of(const Ch* s, size_type pos, size_type n) const{ return find_first_not_of(basic_string(s,n),pos); } _UCXXEXPORT size_type find_first_not_of(const Ch* s, size_type pos = 0) const{ return find_first_not_of(basic_string(s),pos); } _UCXXEXPORT size_type find_first_not_of(Ch c, size_type pos = 0) const{ for(size_type i = pos; i < length() ; ++i){ if(this->operator[](i) != c){ return i; } } return npos; } _UCXXEXPORT size_type find_last_not_of (const basic_string& str, size_type pos = npos) const{ size_type xpos(length() - 1); if(xpos > pos){ xpos = pos; } while(xpos != npos && npos != str.find_first_of(at(xpos))){ --xpos; } return xpos; } _UCXXEXPORT size_type find_last_not_of (const Ch* s, size_type pos, size_type n) const{ return find_last_not_of(basic_string(s,n),pos); } _UCXXEXPORT size_type find_last_not_of (const Ch* s, size_type pos = npos) const{ return find_last_not_of(basic_string(s),pos); } _UCXXEXPORT size_type find_last_not_of (Ch c, size_type pos = npos) const{ size_type xpos(length() - 1); if(xpos > pos){ xpos = pos; } while(xpos != npos && Tr::eq(at(xpos), c)){ --xpos; } return xpos; } _UCXXEXPORT basic_string substr(size_type pos = 0, size_type n = npos) const; _UCXXEXPORT int compare(const basic_string& str) const{ size_type rlen = vector::elements; if(rlen > str.elements){ rlen = str.elements; } int retval = Tr::compare(vector::data, str.vector::data, rlen); if(retval == 0){ if(vector::elements < str.elements){ retval = -1; } if(vector::elements > str.elements){ retval = 1; } } return retval; } _UCXXEXPORT int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2=0, size_type n2=npos) const{ size_type len1 = vector::elements - pos1; if(len1 > n1){ len1 = n1; } size_type len2 = str.vector::elements - pos2; if(len2 > n2){ len2 = n2; } size_type rlen = len1; if(rlen > len2){ rlen = len2; } int retval = Tr::compare(vector::data + pos1, str.vector::data + pos2, rlen); if(retval == 0){ if(len1 < len2){ retval = -1; } if(len1 > len2){ retval = 1; } } return retval; } _UCXXEXPORT int compare(const Ch* s) const{ size_type slen = Tr::length(s); size_type rlen = slen; if(rlen > vector::elements){ rlen=vector::elements; } int retval = Tr::compare(vector::data, s, rlen); if(retval==0){ if(vector::elements < slen){ retval = -1; } if(vector::elements > slen){ retval = 1; } } return retval; } _UCXXEXPORT int compare(size_type pos1, size_type n1, const Ch* s, size_type n2 = npos) const{ size_type len1 = vector::elements - pos1; if(len1 > n1){ len1 = n1; } size_type slen = Tr::length(s); size_type len2 = slen; if(len2 > n2){ len2 = n2; } size_type rlen = len1; if(rlen > len2){ rlen = len2; } int retval = Tr::compare(vector::data + pos1, s, rlen); if(retval == 0){ if(len1 < len2){ retval = -1; } if(len1 > len2){ retval = 1; } } return retval; } }; //Functions template _UCXXEXPORT basic_string::basic_string(const Ch* s, const A& al) : vector(al) { if(s!=0){ size_type temp = Tr::length(s); append(s, temp); } } template _UCXXEXPORT basic_string:: basic_string(const basic_string& str, size_type pos, size_type n, const A& al) : vector(al) { if(pos>str.size()){ __throw_out_of_range(); } size_type rlen = str.size() - pos; if( rlen > n){ rlen = n; } resize(rlen); Tr::copy(vector::data, str.vector::data + pos, vector::elements); } template _UCXXEXPORT basic_string& basic_string::operator=(const basic_string & str) { if(&str == this){ //Check if we are doing a=a return *this; } vector::clear(); resize(str.elements); Tr::copy( vector::data, str.vector::data, str.elements); return *this; } template _UCXXEXPORT typename basic_string::size_type basic_string::find (const basic_string& str, size_type pos) const { if(str.length() > length()){ return npos; } size_type max_string_start = 1 + length() - str.length(); for(size_type i = pos; i < max_string_start; ++i){ if(str == substr(i, str.length())){ return i; } } return npos; } template _UCXXEXPORT basic_string basic_string::substr(size_type pos, size_type n) const { if(pos > vector::elements){ __throw_out_of_range(); } size_type rlen = vector::elements - pos; if(rlen > n){ rlen = n; } return basic_string(vector::data + pos,rlen); } #ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ #ifndef __UCLIBCXX_COMPILE_STRING__ #ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__ template <> _UCXXEXPORT string::basic_string(const allocator &); template <> _UCXXEXPORT string::basic_string(size_type n, char c, const allocator & ); template <> _UCXXEXPORT string::basic_string(const char* s, const allocator& al); template <> _UCXXEXPORT string::basic_string(const basic_string& str, size_type pos, size_type n, const allocator& al); template <> _UCXXEXPORT string::~basic_string(); #endif template <> _UCXXEXPORT string & string::append(const char * s, size_type n); template <> _UCXXEXPORT string::size_type string::find(const string & str, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find(const char* s, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find (char c, size_type pos) const; template <> _UCXXEXPORT string::size_type string::rfind(const string & str, size_type pos) const; template <> _UCXXEXPORT string::size_type string::rfind(char c, size_type pos) const; template <> _UCXXEXPORT string::size_type string::rfind(const char* s, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_first_of(const string &, size_type) const; template <> _UCXXEXPORT string::size_type string::find_first_of(const char *, size_type pos, size_type n) const; template <> _UCXXEXPORT string::size_type string::find_first_of(const char*, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_first_of(char c, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_last_of (const string & , size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos, size_type n) const; template <> _UCXXEXPORT string::size_type string::find_last_of (const char* s, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_last_of (char c, size_type pos) const; template <> _UCXXEXPORT string::size_type string::find_first_not_of(const string &, size_type) const; template <> _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type, size_type) const; template <> _UCXXEXPORT string::size_type string::find_first_not_of(const char*, size_type) const; template <> _UCXXEXPORT string::size_type string::find_first_not_of(char c, size_type) const; template <> _UCXXEXPORT int string::compare(const string & str) const; template <> _UCXXEXPORT int string::compare( size_type pos1, size_type n1, const string & str, size_type pos2, size_type n2) const; template <> _UCXXEXPORT string string::substr(size_type pos, size_type n) const; template <> _UCXXEXPORT string & string::operator=(const string & str); template <> _UCXXEXPORT string & string::operator=(const char * s); #endif #endif //typedef basic_string string; template _UCXXEXPORT basic_string operator+(const basic_string& lhs, const basic_string& rhs) { basic_string temp(lhs); temp.append(rhs); return temp; } template _UCXXEXPORT basic_string operator+(const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); temp.append(rhs); return temp; } template _UCXXEXPORT basic_string operator+(charT lhs, const basic_string& rhs) { basic_string temp(1, lhs); temp.append(rhs); return temp; } template _UCXXEXPORT basic_string operator+(const basic_string& lhs, const charT* rhs) { basic_string temp(lhs); temp.append(rhs); return temp; } template _UCXXEXPORT basic_string operator+(const basic_string& lhs, charT rhs) { basic_string temp(lhs); temp+=rhs; return temp; } template _UCXXEXPORT bool operator==(const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) == 0){ return true; } return false; } template _UCXXEXPORT bool operator==(const charT* lhs, const basic_string& rhs) { if(rhs.compare(lhs) == 0){ return true; } return false; } template _UCXXEXPORT bool operator==(const basic_string& lhs, const charT* rhs) { if(lhs.compare(rhs)==0){ return true; } return false; } template _UCXXEXPORT bool operator!=(const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) !=0){ return true; } return false; } template _UCXXEXPORT bool operator!=(const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); return (temp != rhs); } template _UCXXEXPORT bool operator!=(const basic_string& lhs, const charT* rhs) { basic_string temp(rhs); return (lhs != temp); } template _UCXXEXPORT bool operator< (const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) < 0){ return true; } return false; } template _UCXXEXPORT bool operator< (const basic_string& lhs, const charT* rhs) { basic_string temp(rhs); if(lhs.compare(rhs) < 0){ return true; } return false; } template _UCXXEXPORT bool operator< (const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); if(temp.compare(rhs) < 0){ return true; } return false; } template _UCXXEXPORT bool operator> (const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) > 0){ return true; } return false; } template _UCXXEXPORT bool operator> (const basic_string& lhs, const charT* rhs) { basic_string temp(rhs); if(lhs.compare(rhs) > 0){ return true; } return false; } template _UCXXEXPORT bool operator> (const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); if(temp.compare(rhs) > 0){ return true; } return false; } template _UCXXEXPORT bool operator<=(const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) <=0){ return true; } return false; } template _UCXXEXPORT bool operator<=(const basic_string& lhs, const charT* rhs) { basic_string temp(rhs); if(lhs.compare(temp) <=0 ){ return true; } return false; } template _UCXXEXPORT bool operator<=(const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); if(temp.compare(rhs) <= 0){ return true; } return false; } template _UCXXEXPORT bool operator>=(const basic_string& lhs, const basic_string& rhs) { if(lhs.compare(rhs) >=0){ return true; } return false; } template _UCXXEXPORT bool operator>=(const basic_string& lhs, const charT* rhs) { basic_string temp(rhs); if(lhs.compare(temp) >=0 ){ return true; } return false; } template _UCXXEXPORT bool operator>=(const charT* lhs, const basic_string& rhs) { basic_string temp(lhs); if(temp.compare(rhs) >=0 ){ return true; } return false; } template _UCXXEXPORT void swap(basic_string& lhs, basic_string& rhs) { lhs.swap(rhs); } /*template _UCXXEXPORT basic_ostream& operator<<(basic_ostream& os, const basic_string& str) { return os.write(str.data(), str.length()); }*/ #ifdef __UCLIBCXX_EXPAND_STRING_CHAR__ #ifndef __UCLIBCXX_COMPILE_STRING__ //Operators we can avoid duplication of template <> _UCXXEXPORT bool operator==(const string & lhs, const string & rhs); template <> _UCXXEXPORT bool operator==(const char * lhs, const string & rhs); template <> _UCXXEXPORT bool operator==(const string & lhs, const char * rhs); template <> _UCXXEXPORT bool operator!=(const string & lhs, const string & rhs); template <> _UCXXEXPORT bool operator!=(const char * lhs, const string & rhs); template <> _UCXXEXPORT bool operator!=(const string & lhs, const char * rhs); template <> _UCXXEXPORT string operator+(const string & lhs, const char* rhs); template <> _UCXXEXPORT string operator+(const char* lhs, const string & rhs); template <> _UCXXEXPORT string operator+(const string & lhs, const string & rhs); template <> _UCXXEXPORT bool operator> (const string & lhs, const string & rhs); template <> _UCXXEXPORT bool operator< (const string & lhs, const string & rhs); #endif #endif } #endif