// Member templates for the -*- C++ -*- string classes. // Copyright (C) 1994 Free Software Foundation // This file is part of the GNU ANSI C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, 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 General Public License for more details. // You should have received a copy of the GNU General Public License // along with GNU CC; see the file COPYING. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // As a special exception, if you link this library with files // compiled with a GNU compiler to produce an executable, this does not cause // the resulting executable to be covered by the GNU General Public License. // This exception does not however invalidate any other reasons why // the executable file might be covered by the GNU General Public License. // Written by Jason Merrill based upon the specification by Takanori Adachi // in ANSI X3J16/94-0013R2. #include #include template inline void * __bsrep :: operator new (size_t s, size_t extra) { return ::operator new (s + extra); } template inline size_t __bsrep :: #ifdef _G_ALLOC_CONTROL default_frob (size_t s) #else frob_size (size_t s) #endif { size_t i = 16; while (i < s) i *= 2; return i; } template inline __bsrep * __bsrep :: create (size_t extra) { extra = frob_size (extra); Rep *p = new (extra) Rep; p->res = extra; p->ref = 1; return p; } template inline bool __bsrep :: #ifdef _G_ALLOC_CONTROL default_excess (size_t s, size_t r) #else excess_slop (size_t s, size_t r) #endif { return 2 * (s <= 16 ? 16 : s) < r; } template inline bool basic_string :: check_realloc (size_t s) { return (rep->ref > 1 || s > reserve () || Rep::excess_slop (s, reserve ())); } template void basic_string :: alloc (size_t size, bool save) { if (! check_realloc (size)) return; Rep *p = Rep::create (size); if (save) { p->copy (0, data (), length ()); p->len = length (); } else p->len = 0; rep->release (); rep = p; } template basic_string :: basic_string (size_t size, capacity cap) { switch (cap) { default_size: assign (eos (), size); break; reserve: rep = nilRep.grab (); reserve (size); break; default: ; } } template basic_string & basic_string :: replace (size_t pos1, size_t n1, const basic_string& str, size_t pos2, size_t n2) { const size_t len2 = str.length (); if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2) return operator= (str); OUTOFRANGE (pos2 > len2); if (n2 > len2 - pos2) n2 = len2 - pos2; return replace (pos1, n1, str.data () + pos2, n2); } template inline void __bsrep :: copy (size_t pos, const charT *s, size_t n) { if (n) traits::copy (data () + pos, s, n); } template inline void __bsrep :: move (size_t pos, const charT *s, size_t n) { if (n) traits::move (data () + pos, s, n); } template basic_string & basic_string :: replace (size_t pos, size_t n1, const charT* s, size_t n2) { const size_t len = length (); OUTOFRANGE (pos > len); if (n1 > len - pos) n1 = len - pos; LENGTHERROR (len - n1 >= NPOS - n2); size_t newlen = len - n1 + n2; if (check_realloc (newlen)) { Rep *p = Rep::create (newlen); p->copy (0, data (), pos); p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); p->copy (pos, s, n2); rep->release (); rep = p; } else { rep->move (pos + n2, data () + pos + n1, len - (pos + n1)); rep->copy (pos, s, n2); } rep->len = newlen; return *this; } template inline void __bsrep :: set (size_t pos, const charT c, size_t n) { traits::set (data () + pos, c, n); } template basic_string & basic_string :: replace (size_t pos, size_t n1, charT c, size_t n2) { const size_t len = length (); OUTOFRANGE (pos > len); if (n1 > len - pos) n1 = len - pos; LENGTHERROR (len - n1 >= NPOS - n2); size_t newlen = len - n1 + n2; if (check_realloc (newlen)) { Rep *p = Rep::create (newlen); p->copy (0, data (), pos); p->copy (pos + n2, data () + pos + n1, len - (pos + n1)); p->set (pos, c, n2); rep->release (); rep = p; } else { rep->move (pos + n2, data () + pos + n1, len - (pos + n1)); rep->set (pos, c, n2); } rep->len = newlen; return *this; } template void basic_string :: resize (size_t n, charT c) { LENGTHERROR (n == NPOS); if (n > length ()) append (c, n - length ()); else remove (n); } template size_t basic_string :: copy (charT* s, size_t n, size_t pos) { OUTOFRANGE (pos > length ()); if (n > length () - pos) n = length () - pos; traits::copy (s, data () + pos, n); return n; } template size_t basic_string :: find (const charT* s, size_t pos, size_t n) { size_t xpos = pos; for (; xpos + n <= length (); ++xpos) if (traits::eq (data () [xpos], *s) && traits::compare (data () + xpos, s, n) == 0) return xpos; return NPOS; } template inline size_t basic_string :: _find (const charT* ptr, charT c, size_t xpos, size_t len) { for (; xpos < len; ++xpos) if (traits::eq (ptr [xpos], c)) return xpos; return NPOS; } template size_t basic_string :: find (charT c, size_t pos) { return _find (data (), c, pos, length ()); } template size_t basic_string :: rfind (const charT* s, size_t pos, size_t n) { size_t xpos = length () - n; if (xpos > pos) xpos = pos; for (; xpos >= 0; --xpos) if (traits::eq (data () [xpos], *s) && traits::compare (data () + xpos, s, n) == 0) return xpos; return NPOS; } template size_t basic_string :: rfind (charT c, size_t pos) { size_t xpos = length () - 1; if (xpos > pos) xpos = pos; for (; xpos >= 0; --xpos) if (traits::eq (data () [xpos], c)) return xpos; return NPOS; } template size_t basic_string :: find_first_of (const charT* s, size_t pos, size_t n) { size_t xpos = pos; for (; xpos + n <= length (); ++xpos) if (_find (s, data () [xpos], 0, n) != NPOS) return xpos; return NPOS; } template size_t basic_string :: find_last_of (const charT* s, size_t pos, size_t n) { size_t xpos = length () - n; for (; xpos >= 0; --xpos) if (_find (s, data () [xpos], 0, n) != NPOS) return xpos; return NPOS; } template size_t basic_string :: find_first_not_of (const charT* s, size_t pos, size_t n) { size_t xpos = pos; for (; xpos + n <= length (); ++xpos) if (_find (s, data () [xpos], 0, n) == NPOS) return xpos; return NPOS; } template size_t basic_string :: find_first_not_of (charT c, size_t pos) { size_t xpos = pos; for (; xpos < length (); ++xpos) if (traits::ne (data () [xpos], c)) return xpos; return NPOS; } template size_t basic_string :: find_last_not_of (const charT* s, size_t pos, size_t n) { size_t xpos = length () - n; for (; xpos >= 0; --xpos) if (_find (s, data () [xpos], 0, n) == NPOS) return xpos; return NPOS; } template size_t basic_string :: find_last_not_of (charT c, size_t pos) { size_t xpos = length () - 1; for (; xpos >= 0; --xpos) if (traits::ne (data () [xpos], c)) return xpos; return NPOS; } template int basic_string :: compare (const basic_string& str, size_t pos, size_t n) const { OUTOFRANGE (pos > length ()); size_t rlen = length () - pos; if (rlen > n) rlen = n; if (rlen > str.length ()) rlen = str.length (); int r = traits::compare (data () + pos, str.data (), rlen); if (r != 0) return r; if (rlen == n) return 0; return (length () - pos) - str.length (); } template int basic_string :: compare (const charT* s, size_t pos, size_t n) const { OUTOFRANGE (pos > length ()); size_t rlen = length () - pos; if (rlen > n) rlen = n; int r = traits::compare (data () + pos, s, rlen); if (r != 0) return r; return (length () - pos) - n; } template int basic_string :: compare (charT c, size_t pos, size_t n) const { OUTOFRANGE (pos > length ()); size_t end = pos + n; if (end > length ()) end = length (); size_t xpos = pos; for (; xpos < end; ++xpos) if (traits::ne (data () [xpos], c)) return traits::lt (data () [xpos], c) ? -1 : 1; return (length () - pos) - n; } #include // This function is complex to avoid unnecessary shrinking of the string // argument. Does this actually buy us anything? template istream & operator>> (istream &is, basic_string &s) { int w = is.width (0); if (is.ipfx0 ()) { register size_t len = 0; const size_t oldalloc = s.reserve (); register streambuf *sb = is.rdbuf (); s.unique (); while (1) { if (len == oldalloc) goto next; charT ch = sb->sbumpc (); if (ch == EOF) { is.setstate (ios::eofbit); break; } else if (traits::is_del (ch)) { sb->sungetc (); break; } (*s.rep)[len++] = ch; if (--w == 1) break; } s.resize (len); goto done; next: while (1) { charT ch = sb->sbumpc (); if (ch == EOF) { is.setstate (ios::eofbit); break; } else if (traits::is_del (ch)) { sb->sungetc (); break; } s += ch; if (--w == 1) break; } } done: is.isfx (); if (s.length () == 0) is.setstate (ios::failbit); return is; } template ostream & operator<< (ostream &o, basic_string s) { return o.write (s.data (), s.length ()); }