source: NonGTP/Boost/boost/format/format_implementation.hpp @ 857

Revision 857, 10.4 KB checked in by igarcia, 18 years ago (diff)
Line 
1// ----------------------------------------------------------------------------
2// format_implementation.hpp  Implementation of the basic_format class
3// ----------------------------------------------------------------------------
4
5//  Copyright Samuel Krempp 2003. Use, modification, and distribution are
6//  subject to the Boost Software License, Version 1.0. (See accompanying
7//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9//  See http://www.boost.org/libs/format for library home page
10
11
12// ----------------------------------------------------------------------------
13
14#ifndef BOOST_FORMAT_IMPLEMENTATION_HPP
15#define BOOST_FORMAT_IMPLEMENTATION_HPP
16
17#include <boost/config.hpp>
18#include <boost/throw_exception.hpp>
19#include <boost/assert.hpp>
20#include <boost/format/format_class.hpp>
21#include <algorithm> // std::swap
22
23namespace boost {
24
25// ---  basic_format implementation -----------------------------------------//
26
27    template< class Ch, class Tr, class Alloc>
28    basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* str)
29        : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
30          exceptions_(io::all_error_bits)
31    {
32        if( str)
33            parse( str );
34    }
35
36#if !defined(BOOST_NO_STD_LOCALE)
37    template< class Ch, class Tr, class Alloc>
38    basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* str, const std::locale & loc)
39        : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
40          loc_(loc), exceptions_(io::all_error_bits)
41    {
42        if(str) parse( str );
43    }
44
45    template< class Ch, class Tr, class Alloc>
46    basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s, const std::locale & loc)
47        : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
48          loc_(loc), exceptions_(io::all_error_bits)
49    {
50        parse(s); 
51    }
52#endif // ! BOOST_NO_STD_LOCALE
53    template< class Ch, class Tr, class Alloc>
54    io::detail::locale_t basic_format<Ch, Tr, Alloc>::
55    getloc() const {
56        return loc_ ? loc_.get() : io::detail::locale_t();
57    }
58
59    template< class Ch, class Tr, class Alloc>
60    basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s)
61        : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
62          exceptions_(io::all_error_bits)
63    {
64        parse(s); 
65    }
66
67    template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member
68    basic_format<Ch, Tr, Alloc>:: basic_format(const basic_format& x)
69        : items_(x.items_), bound_(x.bound_), style_(x.style_),
70          cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false),
71          prefix_(x.prefix_), exceptions_(x.exceptions_), loc_(x.loc_)
72    {
73    }
74
75    template< class Ch, class Tr, class Alloc>  // just don't copy the buf_ member
76    basic_format<Ch, Tr, Alloc>& basic_format<Ch, Tr, Alloc>::
77    operator= (const basic_format& x) {
78        if(this == &x)
79            return *this;
80        (basic_format<Ch, Tr, Alloc>(x)).swap(*this);
81        return *this;
82    }
83    template< class Ch, class Tr, class Alloc>
84    void  basic_format<Ch, Tr, Alloc>::
85    swap (basic_format & x) {
86        std::swap(exceptions_, x.exceptions_);
87        std::swap(style_, x.style_);
88        std::swap(cur_arg_, x.cur_arg_);
89        std::swap(num_args_, x.num_args_);
90        std::swap(dumped_, x.dumped_);
91
92        items_.swap(x.items_);
93        prefix_.swap(x.prefix_);
94        bound_.swap(x.bound_);
95    }
96
97    template< class Ch, class Tr, class Alloc>
98    unsigned char basic_format<Ch,Tr, Alloc>:: exceptions() const {
99        return exceptions_;
100    }
101
102    template< class Ch, class Tr, class Alloc>
103    unsigned char basic_format<Ch,Tr, Alloc>:: exceptions(unsigned char newexcept) {
104        unsigned char swp = exceptions_;
105        exceptions_ = newexcept;
106        return swp;
107    }
108
109    template<class Ch, class Tr, class Alloc>
110    void basic_format<Ch, Tr, Alloc>::
111    make_or_reuse_data (std::size_t nbitems) {
112#if !defined(BOOST_NO_STD_LOCALE)
113        Ch fill = ( BOOST_USE_FACET(std::ctype<Ch>, getloc()) ). widen(' ');
114#else
115        Ch fill = ' ';
116#endif
117        if(items_.size() == 0)
118            items_.assign( nbitems, format_item_t(fill) );
119        else {
120            if(nbitems>items_.size())
121                items_.resize(nbitems, format_item_t(fill));
122            bound_.resize(0);
123            for(std::size_t i=0; i < nbitems; ++i)
124                items_[i].reset(fill); //  strings are resized, instead of reallocated
125        }
126    }
127
128    template< class Ch, class Tr, class Alloc>
129    basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
130    clear () {
131        // empty the string buffers (except bound arguments)
132        // and make the format object ready for formatting a new set of arguments
133
134        BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast<int>(bound_.size()) );
135
136        for(unsigned long i=0; i<items_.size(); ++i) {
137            // clear converted strings only if the corresponding argument is not  bound :
138            if( bound_.size()==0 || !bound_[ items_[i].argN_ ] )
139                items_[i].res_.resize(0);
140        }
141        cur_arg_=0; dumped_=false;
142        // maybe first arg is bound:
143        if(bound_.size() != 0) {
144            for(; cur_arg_ < num_args_ && bound_[cur_arg_]; ++cur_arg_)
145                {}
146        }
147        return *this;
148    }
149
150    template< class Ch, class Tr, class Alloc>
151    basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
152    clear_binds () {
153        // remove all binds, then clear()
154        bound_.resize(0);
155        clear();
156        return *this;
157    }
158
159    template< class Ch, class Tr, class Alloc>
160    basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
161    clear_bind (int argN) {
162        // remove the bind of ONE argument then clear()
163        if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) {
164            if( exceptions() & io::out_of_range_bit)
165                boost::throw_exception(io::out_of_range(argN, 1, num_args_+1 ) );
166            else return *this;
167        }
168        bound_[argN-1]=false;
169        clear();
170        return *this;
171    }
172
173    template< class Ch, class Tr, class Alloc>
174    typename basic_format<Ch, Tr, Alloc>::string_type
175    basic_format<Ch,Tr, Alloc>::
176    str () const {
177        if(items_.size()==0)
178            return prefix_;
179        if( cur_arg_ < num_args_)
180            if( exceptions() & io::too_few_args_bit )
181                // not enough variables supplied
182                boost::throw_exception(io::too_few_args(cur_arg_, num_args_));
183
184        unsigned long i;
185        string_type res;
186        res.reserve(size());
187        res += prefix_;
188        for(i=0; i < items_.size(); ++i) {
189            const format_item_t& item = items_[i];
190            res += item.res_;
191            if( item.argN_ == format_item_t::argN_tabulation) {
192                BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
193                if( static_cast<size_type>(item.fmtstate_.width_) > res.size() )
194                    res.append( static_cast<size_type>(item.fmtstate_.width_) - res.size(),
195                                        item.fmtstate_.fill_ );
196            }
197            res += item.appendix_;
198        }
199        dumped_=true;
200        return res;
201    }
202    template< class Ch, class Tr, class Alloc>
203    typename std::basic_string<Ch, Tr, Alloc>::size_type  basic_format<Ch,Tr, Alloc>::
204    size () const {
205        BOOST_USING_STD_MAX();
206        size_type sz = prefix_.size();
207        unsigned long i;
208        for(i=0; i < items_.size(); ++i) {
209            const format_item_t& item = items_[i];
210            sz += item.res_.size();
211            if( item.argN_ == format_item_t::argN_tabulation)
212                sz = max BOOST_PREVENT_MACRO_SUBSTITUTION (sz,
213                                        static_cast<size_type>(item.fmtstate_.width_) );
214            sz += item.appendix_.size();
215        }
216        return sz;
217    }
218
219namespace io {
220namespace detail {
221
222    template<class Ch, class Tr, class Alloc, class T>
223    basic_format<Ch, Tr, Alloc>& 
224    bind_arg_body (basic_format<Ch, Tr, Alloc>& self, int argN, const T& val) {
225        // bind one argument to a fixed value
226        // this is persistent over clear() calls, thus also over str() and <<
227        if(self.dumped_)
228            self.clear(); // needed because we will modify cur_arg_
229        if(argN<1 || argN > self.num_args_) {
230            if( self.exceptions() & io::out_of_range_bit )
231                boost::throw_exception(io::out_of_range(argN, 1, self.num_args_+1 ) );
232            else return self;
233        }
234        if(self.bound_.size()==0)
235            self.bound_.assign(self.num_args_,false);
236        else
237            BOOST_ASSERT( self.num_args_ == static_cast<signed int>(self.bound_.size()) );
238        int o_cur_arg = self.cur_arg_;
239        self.cur_arg_ = argN-1; // arrays begin at 0
240
241        self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets..
242        self.operator%(val); // put val at the right place, because cur_arg is set
243   
244
245        // Now re-position cur_arg before leaving :
246        self.cur_arg_ = o_cur_arg;
247        self.bound_[argN-1]=true;
248        if(self.cur_arg_ == argN-1 ) {
249            // hum, now this arg is bound, so move to next free arg
250            while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_])   
251                ++self.cur_arg_;
252        }
253        // In any case, we either have all args, or are on a non-binded arg :
254        BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]);
255        return self;
256    }
257
258    template<class Ch, class Tr, class Alloc, class T> basic_format<Ch, Tr, Alloc>&
259    modify_item_body (basic_format<Ch, Tr, Alloc>& self, int itemN, T manipulator) {
260        // applies a manipulator to the format_item describing a given directive.
261        // this is a permanent change, clear or reset won't cancel that.
262        if(itemN<1 || itemN > static_cast<signed int>(self.items_.size() )) {
263            if( self.exceptions() & io::out_of_range_bit )
264                boost::throw_exception(io::out_of_range(itemN, 1, self.items_.size() ));
265            else return self;
266        }
267        self.items_[itemN-1].fmtstate_. template apply_manip<T> ( manipulator );
268        return self;
269    }
270
271} // namespace detail
272} // namespace io
273} // namespace boost
274
275
276
277#endif  // BOOST_FORMAT_IMPLEMENTATION_HPP
Note: See TracBrowser for help on using the repository browser.