]> git.lyx.org Git - lyx.git/blob - boost/boost/format/format_implementation.hpp
update to boost 1.30.1
[lyx.git] / boost / boost / format / format_implementation.hpp
1 // -*- C++ -*-
2 //  Boost general library format ---------------------------
3 //  See http://www.boost.org for updates, documentation, and revision history.
4
5 //  (C) Samuel Krempp 2001
6 //                  krempp@crans.ens-cachan.fr
7 //  Permission to copy, use, modify, sell and
8 //  distribute this software is granted provided this copyright notice appears
9 //  in all copies. This software is provided "as is" without express or implied
10 //  warranty, and with no claim as to its suitability for any purpose.
11
12 // ideas taken from RĂ¼diger Loos's format class
13 // and Karl Nelson's ofstream
14
15 // ----------------------------------------------------------------------------
16 // format_implementation.hpp  Implementation of the basic_format class
17 // ----------------------------------------------------------------------------
18
19
20 #ifndef BOOST_FORMAT_IMPLEMENTATION_HPP
21 #define BOOST_FORMAT_IMPLEMENTATION_HPP
22
23 #include <boost/throw_exception.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/format/format_class.hpp>
26
27 namespace boost {
28
29 // --------  format:: -------------------------------------------
30 template< class Ch, class Tr>
31 basic_format<Ch, Tr> ::basic_format(const Ch* str)
32     : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
33       items_(), oss_(), exceptions_(io::all_error_bits)
34 {
35     state0_.set_by_stream(oss_);
36     string_t emptyStr;
37     if( !str) str = emptyStr.c_str();
38     parse( str );
39 }
40
41 #ifndef BOOST_NO_STD_LOCALE
42 template< class Ch, class Tr>
43 basic_format<Ch, Tr> ::basic_format(const Ch* str, const std::locale & loc)
44     : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
45       items_(), oss_(), exceptions_(io::all_error_bits)
46 {
47     oss_.imbue( loc );
48     state0_.set_by_stream(oss_);
49     string_t emptyStr;
50     if( !str) str = emptyStr.c_str();
51     parse( str );
52 }
53
54 template< class Ch, class Tr>
55 basic_format<Ch, Tr> ::basic_format(const string_t& s, const std::locale & loc)
56     : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
57       items_(),  oss_(), exceptions_(io::all_error_bits)
58 {
59     oss_.imbue( loc );
60     state0_.set_by_stream(oss_);
61     parse(s);  
62 }
63 #endif //BOOST_NO_STD_LOCALE
64
65 template< class Ch, class Tr>
66 basic_format<Ch, Tr> ::basic_format(const string_t& s)
67     : style_(0), cur_arg_(0), num_args_(0), dumped_(false),
68       items_(),  oss_(), exceptions_(io::all_error_bits)
69 {
70     state0_.set_by_stream(oss_);
71     parse(s);  
72 }
73
74 template< class Ch, class Tr>
75 basic_format<Ch, Tr> :: basic_format(const basic_format& x)
76     : style_(x.style_), cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false), 
77       items_(x.items_), prefix_(x.prefix_), bound_(x.bound_), 
78       oss_(),   // <- we obviously can't copy x.oss_
79       state0_(x.state0_), exceptions_(x.exceptions_)
80
81     state0_.apply_on(oss_);
82
83
84 template< class Ch, class Tr>
85 basic_format<Ch, Tr>& basic_format<Ch, Tr> ::operator= (const basic_format& x)
86 {
87     if(this == &x)
88       return *this;
89     state0_ = x.state0_;
90     state0_.apply_on(oss_);
91
92     // plus all the other (trivial) assignments :
93     exceptions_ = x.exceptions_;
94     items_ = x.items_;
95     prefix_ = x.prefix_;
96     bound_=x.bound_;
97     style_=x.style_; 
98     cur_arg_=x.cur_arg_; 
99     num_args_=x.num_args_;
100     dumped_=x.dumped_;
101     return *this;
102 }
103
104
105 template< class Ch, class Tr>
106 unsigned char basic_format<Ch,Tr> ::exceptions() const 
107 {
108   return exceptions_; 
109 }
110
111 template< class Ch, class Tr>
112 unsigned char basic_format<Ch,Tr> ::exceptions(unsigned char newexcept) 
113
114   unsigned char swp = exceptions_; 
115   exceptions_ = newexcept; 
116   return swp; 
117 }
118
119
120 template< class Ch, class Tr>
121 basic_format<Ch,Tr>& basic_format<Ch,Tr> ::clear()
122   // empty the string buffers (except bound arguments, see clear_binds() )
123   // and make the format object ready for formatting a new set of arguments
124 {
125     BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast<int>(bound_.size()) );
126
127     for(unsigned long i=0; i<items_.size(); ++i){
128       items_[i].state_ = items_[i].ref_state_;
129       // clear converted strings only if the corresponding argument is not  bound :
130       if( bound_.size()==0 || !bound_[ items_[i].argN_ ] )  items_[i].res_.resize(0);
131     }
132     cur_arg_=0; dumped_=false;
133     // maybe first arg is bound:
134     if(bound_.size() != 0)
135       {
136         while(cur_arg_ < num_args_ && bound_[cur_arg_] )      ++cur_arg_;
137       }
138     return *this;
139 }
140
141 template< class Ch, class Tr>
142 basic_format<Ch,Tr>& basic_format<Ch,Tr> ::clear_binds() 
143   // cancel all bindings, and clear()
144 {
145     bound_.resize(0);
146     clear();
147     return *this;
148 }
149
150 template< class Ch, class Tr>
151 basic_format<Ch,Tr>& basic_format<Ch,Tr> ::clear_bind(int argN) 
152   // cancel the binding of ONE argument, and clear()
153 {
154     if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) 
155       {
156         if( exceptions() & io::out_of_range_bit )
157           boost::throw_exception(io::out_of_range()); // arg not in range.
158         else return *this;
159       }
160     bound_[argN-1]=false;
161     clear();
162     return *this;
163 }
164
165
166
167 template< class Ch, class Tr>
168 std::basic_string<Ch,Tr> basic_format<Ch,Tr> ::str() const
169 {
170   dumped_=true;
171   if(items_.size()==0)
172     return prefix_;
173   if( cur_arg_ < num_args_)
174       if( exceptions() & io::too_few_args_bit )
175         boost::throw_exception(io::too_few_args()); // not enough variables have been supplied !
176
177   unsigned long sz = prefix_.size();
178   unsigned long i;
179   for(i=0; i < items_.size(); ++i) 
180     sz += items_[i].res_.size() + items_[i].appendix_.size();
181   string_t res;
182   res.reserve(sz);
183
184   res += prefix_;
185   for(i=0; i < items_.size(); ++i) 
186   {
187     const format_item_t& item = items_[i];
188     res += item.res_;
189     if( item.argN_ == format_item_t::argN_tabulation) 
190     { 
191       BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
192       std::streamsize  n = item.state_.width_ - res.size();
193       if( n > 0 )
194         res.append( n, item.state_.fill_ );
195     }
196     res += item.appendix_;
197   }
198   return res;
199 }
200
201 namespace io {
202 namespace detail {
203
204 template<class Ch, class Tr, class T> 
205 basic_format<Ch, Tr>&  bind_arg_body( basic_format<Ch, Tr>& self, 
206                                       int argN, 
207                                       const T& val)
208   // bind one argument to a fixed value
209   // this is persistent over clear() calls, thus also over str() and <<
210 {
211     if(self.dumped_) self.clear(); // needed, because we will modify cur_arg_..
212     if(argN<1 || argN > self.num_args_) 
213       {
214         if( self.exceptions() & io::out_of_range_bit )
215           boost::throw_exception(io::out_of_range()); // arg not in range.
216         else return self;
217       }
218     if(self.bound_.size()==0) 
219       self.bound_.assign(self.num_args_,false);
220     else 
221       BOOST_ASSERT( self.num_args_ == static_cast<signed int>(self.bound_.size()) );
222     int o_cur_arg = self.cur_arg_;
223     self.cur_arg_ = argN-1; // arrays begin at 0
224
225     self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets..
226     self.operator%(val); // put val at the right place, because cur_arg is set
227     
228
229     // Now re-position cur_arg before leaving :
230     self.cur_arg_ = o_cur_arg; 
231     self.bound_[argN-1]=true;
232     if(self.cur_arg_ == argN-1 )
233       // hum, now this arg is bound, so move to next free arg
234       {
235         while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_])   ++self.cur_arg_;
236       }
237     // In any case, we either have all args, or are on a non-binded arg :
238     BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]);
239     return self;
240 }
241
242 template<class Ch, class Tr, class T> 
243 basic_format<Ch, Tr>&  modify_item_body( basic_format<Ch, Tr>& self,
244                                       int itemN, 
245                                       const T& manipulator)
246   // applies a manipulator to the format_item describing a given directive.
247   // this is a permanent change, clear or clear_binds won't cancel that.
248 {
249   if(itemN<1 || itemN >= static_cast<signed int>(self.items_.size() )) 
250     {
251       if( self.exceptions() & io::out_of_range_bit ) 
252         boost::throw_exception(io::out_of_range()); // item not in range.
253       else return self;
254     }
255   self.items_[itemN-1].ref_state_.apply_manip( manipulator );
256   self.items_[itemN-1].state_ = self.items_[itemN-1].ref_state_;
257   return self;
258 }
259
260 } // namespace detail
261
262 } // namespace io
263
264 } // namespace boost
265
266
267
268 #endif  // BOOST_FORMAT_IMPLEMENTATION_HPP