1  // Helpers for ostream inserters -*- C++ -*-
       2  
       3  // Copyright (C) 2007-2023 Free Software Foundation, Inc.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /** @file bits/ostream_insert.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{ostream}
      28   */
      29  
      30  #ifndef _OSTREAM_INSERT_H
      31  #define _OSTREAM_INSERT_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  #include <iosfwd>
      36  #include <bits/cxxabi_forced.h>
      37  #include <bits/exception_defines.h>
      38  
      39  namespace std _GLIBCXX_VISIBILITY(default)
      40  {
      41  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      42  
      43    /// @cond undocumented
      44  
      45    template<typename _CharT, typename _Traits>
      46      inline void
      47      __ostream_write(basic_ostream<_CharT, _Traits>& __out,
      48  		    const _CharT* __s, streamsize __n)
      49      {
      50        typedef basic_ostream<_CharT, _Traits>       __ostream_type;      
      51        typedef typename __ostream_type::ios_base    __ios_base;
      52  
      53        const streamsize __put = __out.rdbuf()->sputn(__s, __n);
      54        if (__put != __n)
      55  	__out.setstate(__ios_base::badbit);
      56      }
      57  
      58    template<typename _CharT, typename _Traits>
      59      inline void
      60      __ostream_fill(basic_ostream<_CharT, _Traits>& __out, streamsize __n)
      61      {
      62        typedef basic_ostream<_CharT, _Traits>       __ostream_type;      
      63        typedef typename __ostream_type::ios_base    __ios_base;
      64  
      65        const _CharT __c = __out.fill();
      66        for (; __n > 0; --__n)
      67  	{
      68  	  const typename _Traits::int_type __put = __out.rdbuf()->sputc(__c);
      69  	  if (_Traits::eq_int_type(__put, _Traits::eof()))
      70  	    {
      71  	      __out.setstate(__ios_base::badbit);
      72  	      break;
      73  	    }
      74  	}
      75      }
      76  
      77    template<typename _CharT, typename _Traits>
      78      basic_ostream<_CharT, _Traits>&
      79      __ostream_insert(basic_ostream<_CharT, _Traits>& __out,
      80  		     const _CharT* __s, streamsize __n)
      81      {
      82        typedef basic_ostream<_CharT, _Traits>       __ostream_type;
      83        typedef typename __ostream_type::ios_base    __ios_base;
      84  
      85        typename __ostream_type::sentry __cerb(__out);
      86        if (__cerb)
      87  	{
      88  	  __try
      89  	    {
      90  	      const streamsize __w = __out.width();
      91  	      if (__w > __n)
      92  		{
      93  		  const bool __left = ((__out.flags()
      94  					& __ios_base::adjustfield)
      95  				       == __ios_base::left);
      96  		  if (!__left)
      97  		    __ostream_fill(__out, __w - __n);
      98  		  if (__out.good())
      99  		    __ostream_write(__out, __s, __n);
     100  		  if (__left && __out.good())
     101  		    __ostream_fill(__out, __w - __n);
     102  		}
     103  	      else
     104  		__ostream_write(__out, __s, __n);
     105  	      __out.width(0);
     106  	    }
     107  	  __catch(__cxxabiv1::__forced_unwind&)
     108  	    {
     109  	      __out._M_setstate(__ios_base::badbit);
     110  	      __throw_exception_again;
     111  	    }
     112  	  __catch(...)
     113  	    { __out._M_setstate(__ios_base::badbit); }
     114  	}
     115        return __out;
     116      }
     117  
     118    // Inhibit implicit instantiations for required instantiations,
     119    // which are defined via explicit instantiations elsewhere.
     120  #if _GLIBCXX_EXTERN_TEMPLATE
     121    extern template ostream& __ostream_insert(ostream&, const char*, streamsize);
     122  
     123  #ifdef _GLIBCXX_USE_WCHAR_T
     124    extern template wostream& __ostream_insert(wostream&, const wchar_t*,
     125  					     streamsize);
     126  #endif
     127  #endif
     128  
     129    /// @endcond
     130  
     131  _GLIBCXX_END_NAMESPACE_VERSION
     132  } // namespace std
     133  
     134  #endif /* _OSTREAM_INSERT_H */