/*************************************************************************** * * _stringio.cc - definitions of the string extractors * * $Id: _stringio.cc 637130 2008-03-14 15:16:33Z faridz $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Copyright 1994-2008 Rogue Wave Software. * **************************************************************************/ _RWSTD_NAMESPACE (std) { _EXPORT template basic_istream<_CharT, _Traits>& operator>> (basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str) { _RWSTD_ASSERT (0 != __is.rdbuf ()); const _TYPENAME basic_istream<_CharT, _Traits>::sentry __ipfx (__is /* , noskipws = false */); ios_base::iostate __err = ios_base::goodbit; typedef _RWSTD_SIZE_T _SizeT; // count of characters read from stream _SizeT __gcount = 0; _TRY { if (__ipfx) { __str.clear (); // maximum number of characters we can read _RWSTD_SIZE_T __n = __is.width () ? __is.width () : __str.max_size (); basic_streambuf<_CharT, _Traits>* const __rdbuf = __is.rdbuf (); const ctype<_CharT> &__ctp = _USE_FACET (ctype<_CharT>, __is.getloc ()); #ifndef _RWSTD_NO_FRIEND_TEMPLATE while (__n != 0) { const _CharT* const __gptr = __rdbuf->gptr (); const _CharT* const __egptr = __rdbuf->egptr (); // maximum number of characters would want to extract _SizeT __navail = __egptr - __gptr; if (__n < __navail) __navail = __n; if (__navail) { // find the delimeter in the squence if it exists, or // get pointer to end of sequence const _CharT* __pdel = __gptr; for (/**/; __pdel != __egptr; ++__pdel) { const _TYPENAME _Traits::int_type __c = _Traits::to_int_type(*__pdel); if (_Traits::eq_int_type (__c, _Traits::eof ())) { __err = ios_base::eofbit; break; } if (__ctp.is (__ctp.space, *__pdel)) break; } // __pdel is either pointing to a delimiter or one past // the end of the input stream get area. if it is past // the end, then set it to null. if (__pdel == __egptr) { __pdel = 0; } if (__pdel) { __navail = __pdel - __gptr + 1; __n -= __navail - 1; } else if (__n == __navail) __n -= --__navail; else __n -= __navail; // store characters excluding the delimiter __str.append (__gptr, __navail - !!__pdel); __gcount += __navail; // advance gptr() by the number of extracted // characters, including the delimiter __rdbuf->gbump (__navail); // we found a delimiter before the end of the get area, // break out of outer loop if (__pdel) { break; } if (2 > __n && _SizeT (__egptr - __gptr) != __navail) { __err = ios_base::failbit; break; } } else { // n data in buffer, trigger underflow() // note that streambuf may be unbuffered const _TYPENAME _Traits::int_type __c = __rdbuf->sgetc (); if (_Traits::eq_int_type (__c, _Traits::eof ())) { __err = ios_base::eofbit; break; } // convert to char_type so that isspace works correctly const _TYPENAME _Traits::char_type __ch = _Traits::to_char_type (__c); if (__ctp.is (__ctp.space, __ch)) break; __str.push_back (__ch); --__n; __rdbuf->sbumpc (); // increment gcount only _after_ sbumpc() but _before_ // the subsequent call to sgetc() to correctly reflect // the number of extracted characters in the presence // of exceptions thrown from streambuf virtuals ++__gcount; } } #else // if defined (_RWSTD_NO_FRIEND_TEMPLATE) for ( ; __n != 0; ) { const _TYPENAME _Traits::int_type __c (__rdbuf->sgetc ()); if (_Traits::eq_int_type (__c, _Traits::eof ())) { __err = ios_base::eofbit; break; } // convert to char_type so that isspace works correctly const _TYPENAME _Traits::char_type __ch = _Traits::to_char_type (__c); if (__ctp.is (__ctp.space, __ch)) break; __str.push_back (__ch); --__n; __rdbuf->sbumpc (); // increment gcount only _after_ sbumpc() but _before_ // the subsequent call to sgetc() to correctly reflect // the number of extracted characters in the presence // of exceptions thrown from streambuf virtuals ++__gcount; } #endif // if defined (_RWSTD_NO_FRIEND_TEMPLATE) __is.width (0); } } _CATCH (...) { __is.setstate (ios_base::badbit | _RW::__rw_rethrow); } if (!__gcount) __err |= ios_base::failbit; if (__err) __is.setstate (__err); return __is; } _EXPORT template basic_istream<_CharT, _Traits>& getline (basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __delim) { _RWSTD_ASSERT (0 != __is.rdbuf ()); const _TYPENAME basic_istream<_CharT, _Traits>::sentry __ipfx (__is, true /* noskipws */); #ifndef _RWSTD_NO_FRIEND_TEMPLATE ios_base::iostate __err = ios_base::goodbit; typedef _RWSTD_SIZE_T _SizeT; _SizeT __gcount = 0; if (__ipfx) { __str.clear (); // carefuly handle arithmetic overflow _SizeT __n = __str.max_size (); if (__n + _SizeT (1)) ++__n; basic_streambuf<_CharT, _Traits>* const __rdbuf = __is.rdbuf (); _TRY { for ( ; ; ) { typedef _TYPENAME _Traits::int_type int_type; const _CharT* const __gptr = __rdbuf->gptr (); const _CharT* const __egptr = __rdbuf->egptr (); // compute the lesser of the number of characters in the // stream buffer and the size of the destination buffer _SizeT __navail = __egptr - __gptr; if (__n < __navail) __navail = __n; if (__navail) { // find the delimiter in the sequence if it exists const _CharT* const __pdel = _Traits::find (__gptr, __navail, __delim); if (__pdel) { __navail = __pdel - __gptr + 1; __n -= __navail - 1; } else if (__n == __navail) __n -= --__navail; else __n -= __navail; // store characters excluding the delimiter __str.append (__gptr, __navail - !!__pdel); __gcount += __navail; // advance gptr() by the number of extracted // characters, including the delimiter __rdbuf->gbump (__navail); if (__pdel) { break; } if (2 > __n && _SizeT (__egptr - __gptr) != __navail) { __err = ios_base::failbit; break; } } else { // no data in buffer, trigger underflow() // note that streambuf may be unbuffered const int_type __c (__rdbuf->sgetc ()); if (_Traits::eq_int_type (__c, _Traits::eof ())) { __err = ios_base::eofbit; break; } const _CharT __ch = _Traits::to_char_type (__c); if (_Traits::eq (__ch, __delim)) { __rdbuf->sbumpc (); __gcount++; break; } if (2 > __n) { __err = ios_base::failbit; break; } __str += __ch; --__n; __rdbuf->sbumpc (); // increment gcount only _after_ sbumpc() but _before_ // the subsequent call to sgetc() to correctly reflect // the number of extracted characters in the presence // of exceptions thrown from streambuf virtuals ++__gcount; } } } _CATCH (...) { __is.setstate (ios_base::badbit | _RW::__rw_rethrow); } } if (!__gcount) __err |= ios_base::failbit; #else // if defined (_RWSTD_NO_FRIEND_TEMPLATE) ios_base::iostate __err = ios_base::failbit; if (__ipfx) { _TRY { __str.clear (); const _RWSTD_SIZE_T __max_size = __str.max_size (); // FIXME: code commented out to work around an HP aCC 3.14.10 // bug #JAGac86264 // typedef _TYPENAME // basic_string<_CharT, _Traits, _Allocator>::size_type for ( ; ; ) { const _TYPENAME _Traits::int_type __c (__is.rdbuf ()->sgetc ()); if (_Traits::eq_int_type (__c, _Traits::eof ())) { // 21.3.7.9, p7 if (__str.size ()) __err = ios_base::eofbit; else __err = ios_base::eofbit | ios_base::failbit; break; } if (_Traits::eq (_Traits::to_char_type (__c), __delim)) { __is.rdbuf ()->sbumpc (); __err = ios_base::goodbit; break; } if (__max_size <= __str.size ()) break; __str.push_back (_Traits::to_char_type (__c)); __is.rdbuf ()->sbumpc (); } } _CATCH (...) { __is.setstate (ios_base::badbit | _RW::__rw_rethrow); } } #endif // _RWSTD_NO_FRIEND_TEMPLATE if (__err) __is.setstate (__err); return __is; } } // namespace std