Chris@16
|
1 // ----------------------------------------------------------------------------
|
Chris@16
|
2 // internals.hpp : internal structs : stream_format_state, format_item.
|
Chris@16
|
3 // included by format.hpp
|
Chris@16
|
4 // ----------------------------------------------------------------------------
|
Chris@16
|
5
|
Chris@16
|
6 // Copyright Samuel Krempp 2003. Use, modification, and distribution are
|
Chris@16
|
7 // subject to the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9
|
Chris@16
|
10 // See http://www.boost.org/libs/format for library home page
|
Chris@16
|
11
|
Chris@16
|
12 // ----------------------------------------------------------------------------
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_FORMAT_INTERNALS_HPP
|
Chris@16
|
15 #define BOOST_FORMAT_INTERNALS_HPP
|
Chris@16
|
16
|
Chris@16
|
17
|
Chris@16
|
18 #include <string>
|
Chris@16
|
19 #include <boost/assert.hpp>
|
Chris@16
|
20 #include <boost/optional.hpp>
|
Chris@16
|
21 #include <boost/limits.hpp>
|
Chris@16
|
22 #include <boost/format/detail/compat_workarounds.hpp>
|
Chris@16
|
23 #include <boost/format/alt_sstream.hpp> // used as a dummy stream
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost {
|
Chris@16
|
26 namespace io {
|
Chris@16
|
27 namespace detail {
|
Chris@16
|
28
|
Chris@16
|
29
|
Chris@16
|
30 //---- stream_format_state --------------------------------------------------//
|
Chris@16
|
31
|
Chris@16
|
32 // set of params that define the format state of a stream
|
Chris@16
|
33 template<class Ch, class Tr>
|
Chris@16
|
34 struct stream_format_state
|
Chris@16
|
35 {
|
Chris@16
|
36 typedef BOOST_IO_STD basic_ios<Ch, Tr> basic_ios;
|
Chris@16
|
37
|
Chris@16
|
38 stream_format_state(Ch fill) { reset(fill); }
|
Chris@16
|
39 // stream_format_state(const basic_ios& os) { set_by_stream(os); }
|
Chris@16
|
40
|
Chris@16
|
41 void reset(Ch fill); //- sets to default state.
|
Chris@16
|
42 void set_by_stream(const basic_ios& os); //- sets to os's state.
|
Chris@16
|
43 void apply_on(basic_ios & os, //- applies format_state to the stream
|
Chris@16
|
44 boost::io::detail::locale_t * loc_default = 0) const;
|
Chris@16
|
45 template<class T>
|
Chris@16
|
46 void apply_manip(T manipulator) //- modifies state by applying manipulator
|
Chris@16
|
47 { apply_manip_body<Ch, Tr, T>( *this, manipulator) ; }
|
Chris@16
|
48
|
Chris@16
|
49 // --- data ---
|
Chris@16
|
50 std::streamsize width_;
|
Chris@16
|
51 std::streamsize precision_;
|
Chris@16
|
52 Ch fill_;
|
Chris@16
|
53 std::ios_base::fmtflags flags_;
|
Chris@16
|
54 std::ios_base::iostate rdstate_;
|
Chris@16
|
55 std::ios_base::iostate exceptions_;
|
Chris@16
|
56 boost::optional<boost::io::detail::locale_t> loc_;
|
Chris@16
|
57 };
|
Chris@16
|
58
|
Chris@16
|
59
|
Chris@16
|
60 //---- format_item ---------------------------------------------------------//
|
Chris@16
|
61
|
Chris@16
|
62 // stores all parameters that can be specified in format strings
|
Chris@16
|
63 template<class Ch, class Tr, class Alloc>
|
Chris@16
|
64 struct format_item
|
Chris@16
|
65 {
|
Chris@16
|
66 enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 };
|
Chris@16
|
67 // 1. if zeropad is set, all other bits are not,
|
Chris@16
|
68 // 2. if tabulation is set, all others are not.
|
Chris@16
|
69 // centered and spacepad can be mixed freely.
|
Chris@16
|
70 enum arg_values { argN_no_posit = -1, // non-positional directive. will set argN later
|
Chris@16
|
71 argN_tabulation = -2, // tabulation directive. (no argument read)
|
Chris@16
|
72 argN_ignored = -3 // ignored directive. (no argument read)
|
Chris@16
|
73 };
|
Chris@16
|
74 typedef BOOST_IO_STD basic_ios<Ch, Tr> basic_ios;
|
Chris@16
|
75 typedef detail::stream_format_state<Ch, Tr> stream_format_state;
|
Chris@16
|
76 typedef ::std::basic_string<Ch, Tr, Alloc> string_type;
|
Chris@16
|
77
|
Chris@16
|
78 format_item(Ch fill) :argN_(argN_no_posit), fmtstate_(fill),
|
Chris@16
|
79 truncate_(max_streamsize()), pad_scheme_(0) {}
|
Chris@16
|
80 void reset(Ch fill);
|
Chris@16
|
81 void compute_states(); // sets states according to truncate and pad_scheme.
|
Chris@16
|
82
|
Chris@16
|
83 static std::streamsize max_streamsize() {
|
Chris@16
|
84 return (std::numeric_limits<std::streamsize>::max)();
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@16
|
87 // --- data ---
|
Chris@16
|
88 int argN_; //- argument number (starts at 0, eg : %1 => argN=0)
|
Chris@16
|
89 // negative values for items that don't process an argument
|
Chris@16
|
90 string_type res_; //- result of the formatting of this item
|
Chris@16
|
91 string_type appendix_; //- piece of string between this item and the next
|
Chris@16
|
92
|
Chris@16
|
93 stream_format_state fmtstate_;// set by parsing, is only affected by modify_item
|
Chris@16
|
94
|
Chris@16
|
95 std::streamsize truncate_;//- is set for directives like %.5s that ask truncation
|
Chris@16
|
96 unsigned int pad_scheme_;//- several possible padding schemes can mix. see pad_values
|
Chris@16
|
97 };
|
Chris@16
|
98
|
Chris@16
|
99
|
Chris@16
|
100
|
Chris@16
|
101 //--- Definitions ------------------------------------------------------------
|
Chris@16
|
102
|
Chris@16
|
103 // - stream_format_state:: -------------------------------------------------
|
Chris@16
|
104 template<class Ch, class Tr>
|
Chris@16
|
105 void stream_format_state<Ch,Tr>:: apply_on (basic_ios & os,
|
Chris@16
|
106 boost::io::detail::locale_t * loc_default) const {
|
Chris@101
|
107 // If a locale is available, set it first. "os.fill(fill_);" may chrash otherwise.
|
Chris@101
|
108 #if !defined(BOOST_NO_STD_LOCALE)
|
Chris@101
|
109 if(loc_)
|
Chris@101
|
110 os.imbue(loc_.get());
|
Chris@101
|
111 else if(loc_default)
|
Chris@101
|
112 os.imbue(*loc_default);
|
Chris@101
|
113 #else
|
Chris@101
|
114 (void) loc_default; // keep compiler quiet if we don't support locales
|
Chris@101
|
115 #endif
|
Chris@16
|
116 // set the state of this stream according to our params
|
Chris@16
|
117 if(width_ != -1)
|
Chris@16
|
118 os.width(width_);
|
Chris@16
|
119 if(precision_ != -1)
|
Chris@16
|
120 os.precision(precision_);
|
Chris@16
|
121 if(fill_ != 0)
|
Chris@16
|
122 os.fill(fill_);
|
Chris@16
|
123 os.flags(flags_);
|
Chris@16
|
124 os.clear(rdstate_);
|
Chris@16
|
125 os.exceptions(exceptions_);
|
Chris@16
|
126 }
|
Chris@16
|
127
|
Chris@16
|
128 template<class Ch, class Tr>
|
Chris@16
|
129 void stream_format_state<Ch,Tr>:: set_by_stream(const basic_ios& os) {
|
Chris@16
|
130 // set our params according to the state of this stream
|
Chris@16
|
131 flags_ = os.flags();
|
Chris@16
|
132 width_ = os.width();
|
Chris@16
|
133 precision_ = os.precision();
|
Chris@16
|
134 fill_ = os.fill();
|
Chris@16
|
135 rdstate_ = os.rdstate();
|
Chris@16
|
136 exceptions_ = os.exceptions();
|
Chris@16
|
137 }
|
Chris@16
|
138
|
Chris@16
|
139
|
Chris@16
|
140 template<class Ch, class Tr, class T>
|
Chris@16
|
141 void apply_manip_body( stream_format_state<Ch, Tr>& self,
|
Chris@16
|
142 T manipulator) {
|
Chris@16
|
143 // modify our params according to the manipulator
|
Chris@16
|
144 basic_oaltstringstream<Ch, Tr> ss;
|
Chris@16
|
145 self.apply_on( ss );
|
Chris@16
|
146 ss << manipulator;
|
Chris@16
|
147 self.set_by_stream( ss );
|
Chris@16
|
148 }
|
Chris@16
|
149
|
Chris@16
|
150 template<class Ch, class Tr> inline
|
Chris@16
|
151 void stream_format_state<Ch,Tr>:: reset(Ch fill) {
|
Chris@16
|
152 // set our params to standard's default state. cf 27.4.4.1 of the C++ norm
|
Chris@16
|
153 width_=0; precision_=6;
|
Chris@16
|
154 fill_=fill; // default is widen(' '), but we cant compute it without the locale
|
Chris@16
|
155 flags_ = std::ios_base::dec | std::ios_base::skipws;
|
Chris@16
|
156 // the adjust_field part is left equal to 0, which means right.
|
Chris@16
|
157 exceptions_ = std::ios_base::goodbit;
|
Chris@16
|
158 rdstate_ = std::ios_base::goodbit;
|
Chris@16
|
159 }
|
Chris@16
|
160
|
Chris@16
|
161
|
Chris@16
|
162 // --- format_item:: --------------------------------------------------------
|
Chris@16
|
163
|
Chris@16
|
164 template<class Ch, class Tr, class Alloc>
|
Chris@16
|
165 void format_item<Ch, Tr, Alloc>::
|
Chris@16
|
166 reset (Ch fill) {
|
Chris@16
|
167 argN_=argN_no_posit; truncate_ = max_streamsize(); pad_scheme_ =0;
|
Chris@16
|
168 res_.resize(0); appendix_.resize(0);
|
Chris@16
|
169 fmtstate_.reset(fill);
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 template<class Ch, class Tr, class Alloc>
|
Chris@16
|
173 void format_item<Ch, Tr, Alloc>::
|
Chris@16
|
174 compute_states() {
|
Chris@16
|
175 // reflect pad_scheme_ on fmt_state_
|
Chris@16
|
176 // because some pad_schemes has complex consequences on several state params.
|
Chris@16
|
177 if(pad_scheme_ & zeropad) {
|
Chris@16
|
178 // ignore zeropad in left alignment :
|
Chris@16
|
179 if(fmtstate_.flags_ & std::ios_base::left) {
|
Chris@16
|
180 BOOST_ASSERT(!(fmtstate_.flags_ &(std::ios_base::adjustfield ^std::ios_base::left)));
|
Chris@16
|
181 // only left bit might be set. (not right, nor internal)
|
Chris@16
|
182 pad_scheme_ = pad_scheme_ & (~zeropad);
|
Chris@16
|
183 }
|
Chris@16
|
184 else {
|
Chris@16
|
185 pad_scheme_ &= ~spacepad; // printf ignores spacepad when zeropadding
|
Chris@16
|
186 fmtstate_.fill_='0';
|
Chris@16
|
187 fmtstate_.flags_ = (fmtstate_.flags_ & ~std::ios_base::adjustfield)
|
Chris@16
|
188 | std::ios_base::internal;
|
Chris@16
|
189 // removes all adjustfield bits, and adds internal.
|
Chris@16
|
190 }
|
Chris@16
|
191 }
|
Chris@16
|
192 if(pad_scheme_ & spacepad) {
|
Chris@16
|
193 if(fmtstate_.flags_ & std::ios_base::showpos)
|
Chris@16
|
194 pad_scheme_ &= ~spacepad;
|
Chris@16
|
195 }
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198
|
Chris@16
|
199 } } } // namespaces boost :: io :: detail
|
Chris@16
|
200
|
Chris@16
|
201
|
Chris@16
|
202 #endif // BOOST_FORMAT_INTERNALS_HPP
|