Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:41

0001 // ----------------------------------------------------------------------------
0002 //  feed_args.hpp :  functions for processing each argument 
0003 //                      (feed, feed_manip, and distribute)
0004 // ----------------------------------------------------------------------------
0005 
0006 //  Copyright Samuel Krempp 2003. Use, modification, and distribution are
0007 //  subject to the Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 //  See http://www.boost.org/libs/format for library home page
0011 
0012 // ----------------------------------------------------------------------------
0013 
0014 #ifndef BOOST_FORMAT_FEED_ARGS_HPP
0015 #define BOOST_FORMAT_FEED_ARGS_HPP
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/assert.hpp>
0019 #include <boost/throw_exception.hpp>
0020 
0021 #include <boost/format/format_class.hpp>
0022 #include <boost/format/group.hpp>
0023 #include <boost/format/detail/msvc_disambiguater.hpp>
0024 
0025 namespace boost {
0026 namespace io {
0027 namespace detail {
0028 
0029     template<class Ch, class Tr, class Alloc>
0030     void mk_str( std::basic_string<Ch,Tr, Alloc> & res, 
0031                  const Ch * beg,
0032                  typename std::basic_string<Ch,Tr,Alloc>::size_type size,
0033                  std::streamsize w, 
0034                  const Ch fill_char,
0035                  std::ios_base::fmtflags f, 
0036                  const Ch prefix_space, // 0 if no space-padding
0037                  bool center) 
0038     // applies centered/left/right  padding  to the string  [beg, beg+size[
0039     // Effects : the result is placed in res.
0040     {
0041         typedef typename std::basic_string<Ch,Tr,Alloc>::size_type size_type;
0042         res.resize(0);
0043         if(w<=0 || static_cast<size_type>(w) <=size) {
0044             // no need to pad.
0045             res.reserve(size + !!prefix_space);
0046             if(prefix_space) 
0047               res.append(1, prefix_space);
0048             if (size)
0049               res.append(beg, size);
0050         }
0051         else { 
0052             std::streamsize n=static_cast<std::streamsize>(w-size-!!prefix_space);
0053             std::streamsize n_after = 0, n_before = 0; 
0054             res.reserve(static_cast<size_type>(w)); // allocate once for the 2 inserts
0055             if(center) 
0056                 n_after = n/2, n_before = n - n_after; 
0057             else 
0058                 if(f & std::ios_base::left)
0059                     n_after = n;
0060                 else
0061                     n_before = n;
0062             // now make the res string :
0063             if(n_before) res.append(static_cast<size_type>(n_before), fill_char);
0064             if(prefix_space) 
0065               res.append(1, prefix_space);
0066             if (size)  
0067               res.append(beg, size);
0068             if(n_after) res.append(static_cast<size_type>(n_after), fill_char);
0069         }
0070     } // -mk_str(..) 
0071 
0072 
0073 #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
0074 // __DECCXX needs to be tricked to disambiguate this simple overload..
0075 // the trick is in "boost/format/msvc_disambiguater.hpp"
0076   
0077     template< class Ch, class Tr, class T> inline
0078     void put_head (BOOST_IO_STD basic_ostream<Ch, Tr> & os, const T& x ) {
0079         disambiguater<Ch, Tr, T>::put_head(os, x, 1L);
0080     }
0081     template< class Ch, class Tr, class T> inline
0082     void put_last (BOOST_IO_STD basic_ostream<Ch, Tr> & os, const T& x ) {
0083         disambiguater<Ch, Tr, T>::put_last(os, x, 1L);
0084     }
0085 
0086 #else  
0087 
0088     template< class Ch, class Tr, class T> inline
0089     void put_head (BOOST_IO_STD basic_ostream<Ch, Tr> &, const T& ) {
0090     }
0091 
0092     template< class Ch, class Tr, class T> inline
0093     void put_head( BOOST_IO_STD basic_ostream<Ch, Tr> & os, const group1<T>& x ) {
0094         os << group_head(x.a1_); // send the first N-1 items, not the last
0095     }
0096 
0097     template< class Ch, class Tr, class T> inline
0098     void put_last( BOOST_IO_STD basic_ostream<Ch, Tr> & os, const T& x ) {
0099         os << x ;
0100     }
0101 
0102     template< class Ch, class Tr, class T> inline
0103     void put_last( BOOST_IO_STD basic_ostream<Ch, Tr> & os, const group1<T>& x ) {
0104         os << group_last(x.a1_); // this selects the last element
0105     }
0106 
0107 #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 
0108     template< class Ch, class Tr, class T> inline
0109     void put_head( BOOST_IO_STD basic_ostream<Ch, Tr> &, T& ) {
0110     }
0111 
0112     template< class Ch, class Tr, class T> inline
0113     void put_last( BOOST_IO_STD basic_ostream<Ch, Tr> & os, T& x) {
0114         os << x ;
0115     }
0116 #endif
0117 #endif  // -__DECCXX workaround
0118 
0119     template< class Ch, class Tr, class T>
0120     void call_put_head(BOOST_IO_STD basic_ostream<Ch, Tr> & os, const void* x) {
0121         put_head(os, *(static_cast<T const *>(x)));
0122     }
0123 
0124     template< class Ch, class Tr, class T>
0125     void call_put_last(BOOST_IO_STD basic_ostream<Ch, Tr> & os, const void* x) {
0126         put_last(os, *(static_cast<T const *>(x)));
0127     }
0128 
0129     template< class Ch, class Tr>
0130     struct put_holder {
0131         template<class T>
0132         put_holder(T& t)
0133           : arg(&t),
0134             put_head(&call_put_head<Ch, Tr, T>),
0135             put_last(&call_put_last<Ch, Tr, T>)
0136         {}
0137         const void* arg;
0138         void (*put_head)(BOOST_IO_STD basic_ostream<Ch, Tr> & os, const void* x);
0139         void (*put_last)(BOOST_IO_STD basic_ostream<Ch, Tr> & os, const void* x);
0140     };
0141     
0142     template< class Ch, class Tr> inline
0143     void put_head( BOOST_IO_STD basic_ostream<Ch, Tr> & os, const put_holder<Ch, Tr>& t) {
0144         t.put_head(os, t.arg);
0145     }
0146     
0147     template< class Ch, class Tr> inline
0148     void put_last( BOOST_IO_STD basic_ostream<Ch, Tr> & os, const put_holder<Ch, Tr>& t) {
0149         t.put_last(os, t.arg);
0150     }
0151 
0152 
0153     template< class Ch, class Tr, class Alloc, class T> 
0154     void put( T x, 
0155               const format_item<Ch, Tr, Alloc>& specs, 
0156               typename basic_format<Ch, Tr, Alloc>::string_type& res, 
0157               typename basic_format<Ch, Tr, Alloc>::internal_streambuf_t & buf,
0158               io::detail::locale_t *loc_p = NULL)
0159     {
0160 #ifdef BOOST_MSVC
0161        // If std::min<unsigned> or std::max<unsigned> are already instantiated
0162        // at this point then we get a blizzard of warning messages when we call
0163        // those templates with std::size_t as arguments.  Weird and very annoyning...
0164 #pragma warning(push)
0165 #pragma warning(disable:4267)
0166 #endif
0167         // does the actual conversion of x, with given params, into a string
0168         // using the supplied stringbuf.
0169 
0170         typedef typename basic_format<Ch, Tr, Alloc>::string_type   string_type;
0171         typedef typename basic_format<Ch, Tr, Alloc>::format_item_t format_item_t;
0172         typedef typename string_type::size_type size_type;
0173 
0174         basic_oaltstringstream<Ch, Tr, Alloc>  oss( &buf);
0175 
0176 #if !defined(BOOST_NO_STD_LOCALE)
0177         if(loc_p != NULL)
0178             oss.imbue(*loc_p);
0179 #endif
0180 
0181         specs.fmtstate_.apply_on(oss, loc_p);
0182 
0183         // the stream format state can be modified by manipulators in the argument :
0184         put_head( oss, x );
0185         // in case x is a group, apply the manip part of it, 
0186         // in order to find width
0187 
0188         const std::ios_base::fmtflags fl=oss.flags();
0189         const bool internal = (fl & std::ios_base::internal) != 0;
0190         const std::streamsize w = oss.width();
0191         const bool two_stepped_padding= internal && (w!=0);
0192       
0193         res.resize(0);
0194         if(! two_stepped_padding) {
0195             if(w>0) // handle padding via mk_str, not natively in stream 
0196                 oss.width(0);
0197             put_last( oss, x);
0198             const Ch * res_beg = buf.pbase();
0199             Ch prefix_space = 0;
0200             if(specs.pad_scheme_ & format_item_t::spacepad)
0201                 if(buf.pcount()== 0 || 
0202                    (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-')  ))
0203                     prefix_space = oss.widen(' ');
0204             size_type res_size = (std::min)(
0205                 (static_cast<size_type>((specs.truncate_ & (std::numeric_limits<size_type>::max)())) - !!prefix_space), 
0206                 buf.pcount() );
0207             mk_str(res, res_beg, res_size, w, oss.fill(), fl, 
0208                    prefix_space, (specs.pad_scheme_ & format_item_t::centered) !=0 );
0209         }
0210         else  { // 2-stepped padding
0211             // internal can be implied by zeropad, or user-set.
0212             // left, right, and centered alignment overrule internal,
0213             // but spacepad or truncate might be mixed with internal (using manipulator)
0214             put_last( oss, x); // may pad
0215             const Ch * res_beg = buf.pbase();
0216             size_type res_size = buf.pcount();
0217             bool prefix_space=false;
0218             if(specs.pad_scheme_ & format_item_t::spacepad)
0219                 if(buf.pcount()== 0 || 
0220                    (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-')  ))
0221                     prefix_space = true;
0222             if(res_size == static_cast<size_type>(w) && w<=specs.truncate_ && !prefix_space) {
0223                 // okay, only one thing was printed and padded, so res is fine
0224                 res.assign(res_beg, res_size);
0225             }
0226             else { //   length w exceeded
0227                 // either it was multi-output with first output padding up all width..
0228                 // either it was one big arg and we are fine.
0229                 // Note that res_size<w is possible  (in case of bad user-defined formatting)
0230                 res.assign(res_beg, res_size);
0231                 res_beg=NULL;  // invalidate pointers.
0232                 
0233                 // make a new stream, to start re-formatting from scratch :
0234                 buf.clear_buffer();
0235                 basic_oaltstringstream<Ch, Tr, Alloc>  oss2( &buf);
0236                 specs.fmtstate_.apply_on(oss2, loc_p);
0237                 put_head( oss2, x );
0238 
0239                 oss2.width(0);
0240                 if(prefix_space)
0241                     oss2 << ' ';
0242                 put_last(oss2, x );
0243                 if(buf.pcount()==0 && specs.pad_scheme_ & format_item_t::spacepad) {
0244                     prefix_space =true;
0245                     oss2 << ' ';
0246                 }
0247                 // we now have the minimal-length output
0248                 const Ch * tmp_beg = buf.pbase();
0249                 size_type tmp_size = (std::min)(
0250                     (static_cast<size_type>(specs.truncate_ & (std::numeric_limits<size_type>::max)())),
0251                     buf.pcount());
0252                 
0253                 if(static_cast<size_type>(w) <= tmp_size) { 
0254                     // minimal length is already >= w, so no padding (cool!)
0255                         res.assign(tmp_beg, tmp_size);
0256                 }
0257                 else { // hum..  we need to pad (multi_output, or spacepad present)
0258                     //find where we should pad
0259                     size_type sz = (std::min)(res_size + (prefix_space ? 1 : 0), tmp_size);
0260                     size_type i = prefix_space;
0261                     for(; i<sz && tmp_beg[i] == res[i - (prefix_space ? 1 : 0)]; ++i) {}
0262                     if(i>=tmp_size) i=prefix_space;
0263                     res.assign(tmp_beg, i);
0264                                         std::streamsize d = w - static_cast<std::streamsize>(tmp_size);
0265                                         BOOST_ASSERT(d>0);
0266                     res.append(static_cast<size_type>( d ), oss2.fill());
0267                     res.append(tmp_beg+i, tmp_size-i);
0268                     BOOST_ASSERT(i+(tmp_size-i)+(std::max)(d,(std::streamsize)0) 
0269                                  == static_cast<size_type>(w));
0270                     BOOST_ASSERT(res.size() == static_cast<size_type>(w));
0271                 }
0272             }
0273         }
0274         buf.clear_buffer();
0275 #ifdef BOOST_MSVC
0276 #pragma warning(pop)
0277 #endif
0278     } // end- put(..)
0279 
0280 
0281     template< class Ch, class Tr, class Alloc, class T> 
0282     void distribute (basic_format<Ch,Tr, Alloc>& self, T x) {
0283         // call put(x, ..) on every occurrence of the current argument :
0284         if(self.cur_arg_ >= self.num_args_)  {
0285             if( self.exceptions() & too_many_args_bit )
0286                 boost::throw_exception(too_many_args(self.cur_arg_, self.num_args_)); 
0287             else return;
0288         }
0289         for(unsigned long i=0; i < self.items_.size(); ++i) {
0290             if(self.items_[i].argN_ == self.cur_arg_) {
0291                 put<Ch, Tr, Alloc, T> (x, self.items_[i], self.items_[i].res_, 
0292                                 self.buf_, boost::get_pointer(self.loc_) );
0293             }
0294         }
0295     }
0296 
0297     template<class Ch, class Tr, class Alloc, class T> 
0298     basic_format<Ch, Tr, Alloc>&  
0299     feed_impl (basic_format<Ch,Tr, Alloc>& self, T x) {
0300         if(self.dumped_) self.clear();
0301         distribute<Ch, Tr, Alloc, T> (self, x);
0302         ++self.cur_arg_;
0303         if(self.bound_.size() != 0) {
0304                 while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] )
0305                     ++self.cur_arg_;
0306         }
0307         return self;
0308     }
0309 
0310     template<class Ch, class Tr, class Alloc, class T> inline
0311     basic_format<Ch, Tr, Alloc>&  
0312     feed (basic_format<Ch,Tr, Alloc>& self, T x) {
0313         return feed_impl<Ch, Tr, Alloc, const put_holder<Ch, Tr>&>(self, put_holder<Ch, Tr>(x));
0314     }
0315     
0316 } // namespace detail
0317 } // namespace io
0318 } // namespace boost
0319 
0320 
0321 #endif //  BOOST_FORMAT_FEED_ARGS_HPP