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