Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:54

0001 // ----------------------------------------------------------------------------
0002 // format_implementation.hpp  Implementation of the basic_format class
0003 // ----------------------------------------------------------------------------
0004 
0005 //  Copyright Samuel Krempp 2003. Use, modification, and distribution are
0006 //  subject to the Boost Software License, Version 1.0. (See accompanying
0007 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 //  See http://www.boost.org/libs/format for library home page
0010 
0011 
0012 // ----------------------------------------------------------------------------
0013 
0014 #ifndef BOOST_FORMAT_IMPLEMENTATION_HPP
0015 #define BOOST_FORMAT_IMPLEMENTATION_HPP
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/throw_exception.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/format/format_class.hpp>
0021 #include <algorithm> // std::swap
0022 
0023 namespace boost {
0024 
0025 // ---  basic_format implementation -----------------------------------------//
0026 
0027     template< class Ch, class Tr, class Alloc>
0028     basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* s)
0029         : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
0030           exceptions_(io::all_error_bits)
0031     {
0032         if( s)
0033             parse( s );
0034     }
0035 
0036 #if !defined(BOOST_NO_STD_LOCALE)
0037     template< class Ch, class Tr, class Alloc>
0038     basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* s, const std::locale & loc)
0039         : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
0040           exceptions_(io::all_error_bits), loc_(loc)
0041     {
0042         if(s) parse( s );
0043     }
0044 
0045     template< class Ch, class Tr, class Alloc>
0046     basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s, const std::locale & loc)
0047         : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
0048           exceptions_(io::all_error_bits), loc_(loc)
0049     {
0050         parse(s);  
0051     }
0052 #endif // ! BOOST_NO_STD_LOCALE
0053     template< class Ch, class Tr, class Alloc>
0054     io::detail::locale_t basic_format<Ch, Tr, Alloc>:: 
0055     getloc() const {
0056         return loc_ ? loc_.get() : io::detail::locale_t(); 
0057     }
0058 
0059     template< class Ch, class Tr, class Alloc>
0060     basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s)
0061         : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
0062           exceptions_(io::all_error_bits)
0063     {
0064         parse(s);  
0065     }
0066 
0067     template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member
0068     basic_format<Ch, Tr, Alloc>:: basic_format(const basic_format& x)
0069         : items_(x.items_), bound_(x.bound_), style_(x.style_),
0070           cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(x.dumped_),
0071           prefix_(x.prefix_), exceptions_(x.exceptions_), loc_(x.loc_)
0072     {
0073     }
0074 
0075     template< class Ch, class Tr, class Alloc>  // just don't copy the buf_ member
0076     basic_format<Ch, Tr, Alloc>& basic_format<Ch, Tr, Alloc>:: 
0077     operator= (const basic_format& x) {
0078         if(this == &x)
0079             return *this;
0080         (basic_format<Ch, Tr, Alloc>(x)).swap(*this);
0081         return *this;
0082     }
0083     template< class Ch, class Tr, class Alloc>
0084     void  basic_format<Ch, Tr, Alloc>:: 
0085     swap (basic_format & x) {
0086         std::swap(exceptions_, x.exceptions_);
0087         std::swap(style_, x.style_); 
0088         std::swap(cur_arg_, x.cur_arg_); 
0089         std::swap(num_args_, x.num_args_);
0090         std::swap(dumped_, x.dumped_);
0091 
0092         items_.swap(x.items_);
0093         prefix_.swap(x.prefix_);
0094         bound_.swap(x.bound_);
0095     }
0096 
0097     template< class Ch, class Tr, class Alloc>
0098     unsigned char basic_format<Ch,Tr, Alloc>:: exceptions() const {
0099         return exceptions_; 
0100     }
0101 
0102     template< class Ch, class Tr, class Alloc>
0103     unsigned char basic_format<Ch,Tr, Alloc>:: exceptions(unsigned char newexcept) { 
0104         unsigned char swp = exceptions_; 
0105         exceptions_ = newexcept; 
0106         return swp; 
0107     }
0108 
0109     template<class Ch, class Tr, class Alloc>
0110     void basic_format<Ch, Tr, Alloc>:: 
0111     make_or_reuse_data (std::size_t nbitems) {
0112 #if !defined(BOOST_NO_STD_LOCALE)
0113         Ch fill = ( BOOST_USE_FACET(std::ctype<Ch>, getloc()) ). widen(' ');
0114 #else
0115         Ch fill = ' ';
0116 #endif
0117         if(items_.size() == 0)
0118             items_.assign( nbitems, format_item_t(fill) );
0119         else {
0120             if(nbitems>items_.size())
0121                 items_.resize(nbitems, format_item_t(fill));
0122             bound_.resize(0);
0123             for(std::size_t i=0; i < nbitems; ++i)
0124                 items_[i].reset(fill); //  strings are resized, instead of reallocated
0125         }
0126         prefix_.resize(0);
0127     }
0128 
0129     template< class Ch, class Tr, class Alloc>
0130     basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>:: 
0131     clear () {
0132         // empty the string buffers (except bound arguments)
0133         // and make the format object ready for formatting a new set of arguments
0134 
0135         BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast<int>(bound_.size()) );
0136 
0137         for(unsigned long i=0; i<items_.size(); ++i) {
0138             // clear converted strings only if the corresponding argument is not  bound :
0139             if( bound_.size()==0 || items_[i].argN_<0 || !bound_[ items_[i].argN_ ] )
0140                 items_[i].res_.resize(0);
0141         }
0142         cur_arg_=0; dumped_=false;
0143         // maybe first arg is bound:
0144         if(bound_.size() != 0) {
0145             for(; cur_arg_ < num_args_ && bound_[cur_arg_]; ++cur_arg_)
0146                 {}
0147         }
0148         return *this;
0149     }
0150 
0151     template< class Ch, class Tr, class Alloc>
0152     basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>:: 
0153     clear_binds () {
0154         // remove all binds, then clear()
0155         bound_.resize(0);
0156         clear();
0157         return *this;
0158     }
0159 
0160     template< class Ch, class Tr, class Alloc>
0161     basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>:: 
0162     clear_bind (int argN) {
0163         // remove the bind of ONE argument then clear()
0164         if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) {
0165             if( exceptions() & io::out_of_range_bit)
0166                 boost::throw_exception(io::out_of_range(argN, 1, num_args_+1 ) ); 
0167             else return *this;
0168         }
0169         bound_[argN-1]=false;
0170         clear();
0171         return *this;
0172     }
0173 
0174     template< class Ch, class Tr, class Alloc>
0175     int basic_format<Ch,Tr, Alloc>::
0176     bound_args() const {
0177         if(bound_.size()==0)
0178             return 0;
0179         int n=0;
0180         for(int i=0; i<num_args_ ; ++i)
0181             if(bound_[i])
0182                 ++n;
0183         return n;
0184     }
0185 
0186     template< class Ch, class Tr, class Alloc>
0187     int basic_format<Ch,Tr, Alloc>::
0188     fed_args() const {
0189         if(bound_.size()==0)
0190             return cur_arg_;
0191         int n=0;
0192         for(int i=0; i<cur_arg_ ; ++i)
0193             if(!bound_[i])
0194                 ++n;
0195         return n;
0196     }
0197 
0198     template< class Ch, class Tr, class Alloc>
0199     int basic_format<Ch,Tr, Alloc>::
0200     cur_arg() const {
0201       return cur_arg_+1; }
0202 
0203     template< class Ch, class Tr, class Alloc>
0204     int basic_format<Ch,Tr, Alloc>::
0205     remaining_args() const {
0206         if(bound_.size()==0)
0207             return num_args_-cur_arg_;
0208         int n=0;
0209         for(int i=cur_arg_; i<num_args_ ; ++i)
0210             if(!bound_[i])
0211                 ++n;
0212         return n;
0213     }
0214 
0215     template< class Ch, class Tr, class Alloc>
0216     typename basic_format<Ch, Tr, Alloc>::string_type 
0217     basic_format<Ch,Tr, Alloc>:: 
0218     str () const {
0219         if(items_.size()==0)
0220             return prefix_;
0221         if( cur_arg_ < num_args_)
0222             if( exceptions() & io::too_few_args_bit )
0223                 // not enough variables supplied
0224                 boost::throw_exception(io::too_few_args(cur_arg_, num_args_)); 
0225 
0226         unsigned long i;
0227         string_type res;
0228         res.reserve(size());
0229         res += prefix_;
0230         for(i=0; i < items_.size(); ++i) {
0231             const format_item_t& item = items_[i];
0232             res += item.res_;
0233             if( item.argN_ == format_item_t::argN_tabulation) { 
0234                 BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
0235                 if( static_cast<size_type>(item.fmtstate_.width_) > res.size() )
0236                     res.append( static_cast<size_type>(item.fmtstate_.width_) - res.size(),
0237                                         item.fmtstate_.fill_ );
0238             }
0239             res += item.appendix_;
0240         }
0241         dumped_=true;
0242         return res;
0243     }
0244     template< class Ch, class Tr, class Alloc>
0245     typename std::basic_string<Ch, Tr, Alloc>::size_type  basic_format<Ch,Tr, Alloc>:: 
0246     size () const {
0247 #ifdef BOOST_MSVC
0248        // If std::min<unsigned> or std::max<unsigned> are already instantiated
0249        // at this point then we get a blizzard of warning messages when we call
0250        // those templates with std::size_t as arguments.  Weird and very annoyning...
0251 #pragma warning(push)
0252 #pragma warning(disable:4267)
0253 #endif
0254         BOOST_USING_STD_MAX();
0255         size_type sz = prefix_.size();
0256         unsigned long i;
0257         for(i=0; i < items_.size(); ++i) {
0258             const format_item_t& item = items_[i];
0259             sz += item.res_.size();
0260             if( item.argN_ == format_item_t::argN_tabulation)
0261                 sz = max BOOST_PREVENT_MACRO_SUBSTITUTION (sz,
0262                                         static_cast<size_type>(item.fmtstate_.width_) );
0263             sz += item.appendix_.size();
0264         }
0265         return sz;
0266 #ifdef BOOST_MSVC
0267 #pragma warning(pop)
0268 #endif
0269     }
0270 
0271 namespace io {
0272 namespace detail {
0273 
0274     template<class Ch, class Tr, class Alloc, class T> 
0275     basic_format<Ch, Tr, Alloc>&  
0276     bind_arg_body (basic_format<Ch, Tr, Alloc>& self, int argN, const T& val) {
0277         // bind one argument to a fixed value
0278         // this is persistent over clear() calls, thus also over str() and <<
0279         if(self.dumped_) 
0280             self.clear(); // needed because we will modify cur_arg_
0281         if(argN<1 || argN > self.num_args_) {
0282             if( self.exceptions() & io::out_of_range_bit )
0283                 boost::throw_exception(io::out_of_range(argN, 1, self.num_args_+1 ) );
0284             else return self;
0285         }
0286         if(self.bound_.size()==0) 
0287             self.bound_.assign(self.num_args_,false);
0288         else 
0289             BOOST_ASSERT( self.num_args_ == static_cast<signed int>(self.bound_.size()) );
0290         int o_cur_arg = self.cur_arg_;
0291         self.cur_arg_ = argN-1; // arrays begin at 0
0292 
0293         self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets..
0294         self.operator%(val); // put val at the right place, because cur_arg is set
0295     
0296 
0297         // Now re-position cur_arg before leaving :
0298         self.cur_arg_ = o_cur_arg; 
0299         self.bound_[argN-1]=true;
0300         if(self.cur_arg_ == argN-1 ) {
0301             // hum, now this arg is bound, so move to next free arg
0302             while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_])   
0303                 ++self.cur_arg_;
0304         }
0305         // In any case, we either have all args, or are on an unbound arg :
0306         BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]);
0307         return self;
0308     }
0309 
0310     template<class Ch, class Tr, class Alloc, class T> basic_format<Ch, Tr, Alloc>&
0311     modify_item_body (basic_format<Ch, Tr, Alloc>& self, int itemN, T manipulator) {
0312         // applies a manipulator to the format_item describing a given directive.
0313         // this is a permanent change, clear or reset won't cancel that.
0314         if(itemN<1 || itemN > static_cast<signed int>(self.items_.size() )) {
0315             if( self.exceptions() & io::out_of_range_bit ) 
0316                 boost::throw_exception(io::out_of_range(itemN, 1, static_cast<int>(self.items_.size()) ));
0317             else return self;
0318         }
0319         self.items_[itemN-1].fmtstate_. template apply_manip<T> ( manipulator );
0320         return self;
0321     }
0322 
0323 } // namespace detail
0324 } // namespace io
0325 } // namespace boost
0326 
0327 
0328 
0329 #endif  // BOOST_FORMAT_IMPLEMENTATION_HPP