OSDN Git Service

* include/bits/istream.tcc (getline): Make sure arguments passed
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / istream.tcc
index 21f809d..09339e9 100644 (file)
@@ -44,14 +44,14 @@ namespace std
 {
   template<typename _CharT, typename _Traits>
     basic_istream<_CharT, _Traits>::sentry::
-    sentry(basic_istream<_CharT, _Traits>& __in, bool __noskipws)
+    sentry(basic_istream<_CharT, _Traits>& __in, bool __noskip) : _M_ok(false)
     {
       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
       if (__in.good())
        {
          if (__in.tie())
            __in.tie()->flush();
-         if (!__noskipws && (__in.flags() & ios_base::skipws))
+         if (!__noskip && (__in.flags() & ios_base::skipws))
            {
              const __int_type __eof = traits_type::eof();
              __streambuf_type* __sb = __in.rdbuf();
@@ -59,7 +59,7 @@ namespace std
 
              const __ctype_type& __ct = __check_facet(__in._M_ctype);
              while (!traits_type::eq_int_type(__c, __eof)
-                    && __ct.is(ctype_base::space,
+                    && __ct.is(ctype_base::space, 
                                traits_type::to_char_type(__c)))
                __c = __sb->snextc();
 
@@ -75,7 +75,6 @@ namespace std
        _M_ok = true;
       else
        {
-         _M_ok = false;
          __err |= ios_base::failbit;
          __in.setstate(__err);
        }
@@ -478,7 +477,7 @@ namespace std
        {
          try
            {
-             int_type __cb = this->rdbuf()->sbumpc();
+             const int_type __cb = this->rdbuf()->sbumpc();
              // 27.6.1.1 paragraph 3
              if (!traits_type::eq_int_type(__cb, traits_type::eof()))
                {
@@ -520,8 +519,8 @@ namespace std
                     && !traits_type::eq_int_type(__c, __idelim))
                {
                  *__s++ = traits_type::to_char_type(__c);
-                 __c = __sb->snextc();
                  ++_M_gcount;
+                 __c = __sb->snextc();
                }
              if (traits_type::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
@@ -592,15 +591,15 @@ namespace std
              const int_type __eof = traits_type::eof();
              __streambuf_type* __sb = this->rdbuf();
              int_type __c = __sb->sgetc();
-             --__n;
              
-             while (_M_gcount < __n
+             while (_M_gcount + 1 < __n
                     && !traits_type::eq_int_type(__c, __eof)
                     && !traits_type::eq_int_type(__c, __idelim))
                {
                  streamsize __size = std::min(streamsize(__sb->egptr()
                                                          - __sb->gptr()),
-                                              __n - _M_gcount);
+                                              streamsize(__n - _M_gcount
+                                                         - 1));
                  if (__size > 1)
                    {
                      const char_type* __p = traits_type::find(__sb->gptr(),
@@ -617,8 +616,8 @@ namespace std
                  else
                    {
                      *__s++ = traits_type::to_char_type(__c);
-                     __c = __sb->snextc();
                      ++_M_gcount;
+                     __c = __sb->snextc();
                    }
                }
 
@@ -626,8 +625,8 @@ namespace std
                __err |= ios_base::eofbit;
              else if (traits_type::eq_int_type(__c, __idelim))
                {
+                 ++_M_gcount;            
                  __sb->sbumpc();
-                 ++_M_gcount;
                }
              else
                __err |= ios_base::failbit;
@@ -643,11 +642,97 @@ namespace std
       return *this;
     }
 
+  // We provide three overloads, since the first two are much simpler
+  // than the general case. Also, the latter two can thus adopt the
+  // same "batchy" strategy used by getline above.
+  template<typename _CharT, typename _Traits>
+    basic_istream<_CharT, _Traits>&
+    basic_istream<_CharT, _Traits>::
+    ignore(void)
+    {
+      _M_gcount = 0;
+      sentry __cerb(*this, true);
+      if (__cerb)
+       {
+         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+         try
+           {
+             const int_type __eof = traits_type::eof();
+             __streambuf_type* __sb = this->rdbuf();
+
+             if (traits_type::eq_int_type(__sb->sbumpc(), __eof))
+               __err |= ios_base::eofbit;
+             else
+               _M_gcount = 1;
+           }
+         catch(...)
+           { this->_M_setstate(ios_base::badbit); }
+         if (__err)
+           this->setstate(__err);
+       }
+      return *this;
+    }
+
+  template<typename _CharT, typename _Traits>
+    basic_istream<_CharT, _Traits>&
+    basic_istream<_CharT, _Traits>::
+    ignore(streamsize __n)
+    {
+      if (__n == 1)
+       return ignore();
+      
+      _M_gcount = 0;
+      sentry __cerb(*this, true);
+      if (__cerb && __n > 0)
+       {
+         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+         try
+           {
+             const int_type __eof = traits_type::eof();
+             __streambuf_type* __sb = this->rdbuf();
+             int_type __c = __sb->sgetc();
+             
+             const bool __bound = __n != numeric_limits<streamsize>::max();
+             if (__bound)
+               --__n;
+             while (_M_gcount <= __n
+                    && !traits_type::eq_int_type(__c, __eof))
+               {
+                 streamsize __size = __sb->egptr() - __sb->gptr();
+                 if (__bound)
+                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
+
+                 if (__size > 1)
+                   {
+                     __sb->gbump(__size);
+                     _M_gcount += __size;
+                     __c = __sb->sgetc();
+                   }
+                 else
+                   {
+                     ++_M_gcount;
+                     __c = __sb->snextc();
+                   }             
+               }
+             if (traits_type::eq_int_type(__c, __eof))
+               __err |= ios_base::eofbit;
+           }
+         catch(...)
+           { this->_M_setstate(ios_base::badbit); }
+         if (__err)
+           this->setstate(__err);
+       }
+      return *this;
+    }
+
   template<typename _CharT, typename _Traits>
     basic_istream<_CharT, _Traits>&
     basic_istream<_CharT, _Traits>::
     ignore(streamsize __n, int_type __delim)
     {
+      if (traits_type::eq_int_type(__delim, traits_type::eof()))
+       return ignore(__n);
+
       _M_gcount = 0;
       sentry __cerb(*this, true);
       if (__cerb && __n > 0)
@@ -655,20 +740,46 @@ namespace std
          ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
          try
            {
+             const char_type __cdelim = traits_type::to_char_type(__delim);          
              const int_type __eof = traits_type::eof();
              __streambuf_type* __sb = this->rdbuf();
-             int_type __c;
+             int_type __c = __sb->sgetc();
 
-             __n = std::min(__n, numeric_limits<streamsize>::max());
-             while (_M_gcount < __n
-                    && !traits_type::eq_int_type(__c = __sb->sbumpc(), __eof))
+             const bool __bound = __n != numeric_limits<streamsize>::max();
+             if (__bound)
+               --__n;
+             while (_M_gcount <= __n
+                    && !traits_type::eq_int_type(__c, __eof)
+                    && !traits_type::eq_int_type(__c, __delim))
                {
-                 ++_M_gcount;
-                 if (traits_type::eq_int_type(__c, __delim))
-                   break;
+                 streamsize __size = __sb->egptr() - __sb->gptr();
+                 if (__bound)
+                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
+
+                 if (__size > 1)
+                   {
+                     const char_type* __p = traits_type::find(__sb->gptr(),
+                                                              __size,
+                                                              __cdelim);
+                     if (__p)
+                       __size = __p - __sb->gptr();
+                     __sb->gbump(__size);
+                     _M_gcount += __size;
+                     __c = __sb->sgetc();
+                   }
+                 else
+                   {
+                     ++_M_gcount;
+                     __c = __sb->snextc();
+                   }             
                }
              if (traits_type::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
+             else if (traits_type::eq_int_type(__c, __delim))
+               {
+                 ++_M_gcount;
+                 __sb->sbumpc();
+               }
            }
          catch(...)
            { this->_M_setstate(ios_base::badbit); }
@@ -740,14 +851,10 @@ namespace std
          try
            {
              // Cannot compare int_type with streamsize generically.
-             streamsize __num = this->rdbuf()->in_avail();
-             if (__num >= 0)
-               {
-                 __num = std::min(__num, __n);
-                 if (__num)
-                   _M_gcount = this->rdbuf()->sgetn(__s, __num);
-               }
-             else
+             const streamsize __num = this->rdbuf()->in_avail();
+             if (__num > 0)
+               _M_gcount = this->rdbuf()->sgetn(__s, std::min(__num, __n));
+             else if (__num == -1)
                __err |= ios_base::eofbit;
            }
          catch(...)
@@ -876,7 +983,8 @@ namespace std
          if (!this->fail())
            {
              // 136.  seekp, seekg setting wrong streams?
-             pos_type __p = this->rdbuf()->pubseekpos(__pos, ios_base::in);
+             const pos_type __p = this->rdbuf()->pubseekpos(__pos,
+                                                            ios_base::in);
 
              // 129. Need error indication from seekp() and seekg()
              if (__p == pos_type(off_type(-1)))
@@ -903,8 +1011,8 @@ namespace std
          if (!this->fail())
            {
              // 136.  seekp, seekg setting wrong streams?
-             pos_type __p = this->rdbuf()->pubseekoff(__off, __dir,
-                                                      ios_base::in);
+             const pos_type __p = this->rdbuf()->pubseekoff(__off, __dir,
+                                                            ios_base::in);
 
              // 129. Need error indication from seekp() and seekg()
              if (__p == pos_type(off_type(-1)))
@@ -924,13 +1032,15 @@ namespace std
     operator>>(basic_istream<_CharT, _Traits>& __in, _CharT& __c)
     {
       typedef basic_istream<_CharT, _Traits>           __istream_type;
+      typedef typename __istream_type::int_type         __int_type;
+
       typename __istream_type::sentry __cerb(__in, false);
       if (__cerb)
        {
          ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
          try
            {
-             typename __istream_type::int_type __cb = __in.rdbuf()->sbumpc();
+             const __int_type __cb = __in.rdbuf()->sbumpc();
              if (!_Traits::eq_int_type(__cb, _Traits::eof()))
                __c = _Traits::to_char_type(__cb);
              else
@@ -1043,11 +1153,13 @@ namespace std
        {
          try
            {
+             // Avoid reallocation for common case.
              __str.erase();
-             streamsize __w = __in.width();
-             __size_type __n;
-             __n = __w > 0 ? static_cast<__size_type>(__w) : __str.max_size();
-
+             _CharT __buf[128];
+             __size_type __len = 0;          
+             const streamsize __w = __in.width();
+             const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
+                                             : __str.max_size();
              const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
              const __int_type __eof = _Traits::eof();
              __streambuf_type* __sb = __in.rdbuf();
@@ -1057,10 +1169,17 @@ namespace std
                     && !_Traits::eq_int_type(__c, __eof)
                     && !__ct.is(ctype_base::space, _Traits::to_char_type(__c)))
                {
-                 __str += _Traits::to_char_type(__c);
+                 if (__len == sizeof(__buf) / sizeof(_CharT))
+                   {
+                     __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
+                     __len = 0;
+                   }
+                 __buf[__len++] = _Traits::to_char_type(__c);
                  ++__extracted;
                  __c = __sb->snextc();
                }
+             __str.append(__buf, __len);
+
              if (_Traits::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
              __in.width(0);
@@ -1095,14 +1214,13 @@ namespace std
 
       __size_type __extracted = 0;
       const __size_type __n = __str.max_size();
-      bool __testdelim = false;
       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
       typename __istream_type::sentry __cerb(__in, true);
       if (__cerb)
        {
          try
            {
-             // Avoid reallocation for common case.          
+             // Avoid reallocation for common case.
              __str.erase();
              _CharT __buf[128];
              __size_type __len = 0;
@@ -1130,8 +1248,8 @@ namespace std
                __err |= ios_base::eofbit;
              else if (_Traits::eq_int_type(__c, __idelim))
                {
+                 ++__extracted;                  
                  __sb->sbumpc();
-                 ++__extracted;
                }
              else
                __err |= ios_base::failbit;