Adobe Source Libraries 2.0.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
iomanip.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifdef ADOBE_STD_SERIALIZATION
9
10/**************************************************************************************************/
11
12#ifndef ADOBE_IOMANIP_HPP
13#define ADOBE_IOMANIP_HPP
14
15/**************************************************************************************************/
16
17#include <adobe/config.hpp>
18
19#include <adobe/iomanip_fwd.hpp>
20
21#include <cassert>
22#include <functional>
23#include <iosfwd>
24#include <list>
25#include <sstream>
26#include <stdexcept>
27#include <string>
28
29#include <boost/next_prior.hpp>
30
31#include <adobe/manip.hpp>
32#include <adobe/name.hpp>
34
35
36
37/**************************************************************************************************/
38
39namespace adobe {
40
41/**************************************************************************************************/
42
43namespace implementation {
44
45/**************************************************************************************************/
46
47} // namespace implementation
48
49/**************************************************************************************************/
50
51static const static_name_t bag_name_g = "bag"_name;
52static const static_name_t seq_name_g = "seq"_name;
53static const static_name_t alt_name_g = "alt"_name;
54static const static_name_t atom_name_g = "atom"_name;
55
56/**************************************************************************************************/
57
62
64class format_element_t {
65public:
66 explicit format_element_t(name_t tag = name_t(), const std::string& ident = std::string())
67 : ident_m(ident), num_out_m(0), tag_m(tag), value_m(0) {}
68
69 format_element_t(name_t tag, const serializable_t& value)
70 : num_out_m(0), tag_m(tag), value_m(&value) {}
71
72 name_t tag() const { return tag_m; }
73
74 const serializable_t& value() const {
75 if (!value_m)
76 throw std::runtime_error("invalid value");
77
78 return *value_m;
79 }
80
81 std::string ident_m;
82 std::size_t num_out_m;
83
84private:
85 name_t tag_m;
86 const serializable_t* value_m;
87};
88
89/**************************************************************************************************/
90
92class format_base {
93public:
94 typedef std::ostream stream_type;
95 typedef format_element_t stack_value_type;
96 typedef std::list<stack_value_type> stack_type;
97
98 virtual ~format_base() {}
99
100 virtual void begin_format(stream_type& os) { push_stack(os); }
101 virtual void end_format(stream_type& os) { pop_stack(os); }
102
103 virtual void begin_bag(stream_type& os, const std::string&) { push_stack(os); }
104 virtual void end_bag(stream_type& os) { pop_stack(os); }
105
106 virtual void begin_sequence(stream_type& os) { push_stack(os); }
107 virtual void end_sequence(stream_type& os) { pop_stack(os); }
108
109 virtual void begin_alternate(stream_type& os) { push_stack(os); }
110 virtual void end_alternate(stream_type& os) { pop_stack(os); }
111
112 virtual void begin_atom(stream_type& os, const serializable_t&) { push_stack(os); }
113 virtual void end_atom(stream_type& os) { pop_stack(os); }
114
115 format_base() : depth_m(0) {}
116
117 virtual std::size_t depth() { return depth_m; }
118
119 virtual std::size_t stack_depth() { return stack_m.size(); }
120
121protected:
122 void push_stack(stream_type& os, const stack_value_type& element = format_element_t()) {
123 stack_m.push_front(element);
124 stack_event(os, true);
125 }
126
127 void pop_stack(stream_type& os) {
128 assert(stack_m.empty() == false);
129 stack_event(os, false);
130 stack_m.pop_front();
131 }
132
133 const stack_value_type& stack_top() const { return stack_n(0); }
134
135 stack_value_type& stack_top() { return stack_n(0); }
136
137 const stack_value_type& stack_n(std::size_t n) const {
138 if (n >= stack_m.size()) {
139 std::stringstream buf;
140 buf << "stack_n: n(" << static_cast<unsigned int>(n) << ") > size("
141 << static_cast<unsigned int>(stack_m.size()) << ").";
142 throw std::range_error(buf.str());
143 }
144
145 return *boost::next(stack_m.begin(), n);
146 }
147
148 stack_value_type& stack_n(std::size_t n) {
149 if (n >= stack_m.size()) {
150 std::stringstream buf;
151 buf << "stack_n: n(" << static_cast<unsigned int>(n) << ") > size("
152 << static_cast<unsigned int>(stack_m.size()) << ").";
153 throw std::range_error(buf.str());
154 }
155
156 return *boost::next(stack_m.begin(), n);
157 }
158
159 void up() { ++depth_m; }
160
161 void down() {
162 std::size_t temp = (std::max)(std::size_t(0), --depth_m);
163 depth_m = temp; // use temp to suppress gcc-4.5.0 warning/error
164 }
165
166private:
167 virtual void stack_event(stream_type& os, bool is_push) = 0;
168
169 std::size_t depth_m; // note: Visual "depth", NOT the depth of the stack
170 stack_type stack_m;
171};
172
173/**************************************************************************************************/
174
175format_base::stream_type& begin_format(format_base::stream_type& os);
176format_base::stream_type& end_format(format_base::stream_type& os);
177
178format_base::stream_type& end_bag(format_base::stream_type& os);
179
180format_base::stream_type& begin_sequence(format_base::stream_type& os);
181format_base::stream_type& end_sequence(format_base::stream_type& os);
182
183format_base::stream_type& begin_alternate(format_base::stream_type& os);
184format_base::stream_type& end_alternate(format_base::stream_type& os);
185
186format_base::stream_type& end_atom(format_base::stream_type& os);
187
188/**************************************************************************************************/
189
191class indents : public basic_omanipulator<std::size_t, char, std::char_traits<char>> {
192 typedef basic_omanipulator<std::size_t, char, std::char_traits<char>> inherited_t;
193
194public:
195 typedef inherited_t::stream_type stream_type;
196 typedef inherited_t::argument_type argument_type;
197
198 indents(argument_type num) : inherited_t(indents::fct, num) {}
199
200 inherited_t& operator()(argument_type i) {
201 arg_m = i;
202 return *this;
203 }
204
205private:
206 static stream_type& fct(stream_type& os, const argument_type& i) {
207 for (argument_type count(0); count < i; ++count)
208 os.put('\t');
209
210 return os;
211 }
212};
213
214/**************************************************************************************************/
215
217class begin_bag : public basic_omanipulator<std::string, char, std::char_traits<char>> {
218 typedef basic_omanipulator<std::string, char, std::char_traits<char>> inherited_t;
219
220public:
221 typedef inherited_t::stream_type stream_type;
222 typedef inherited_t::argument_type argument_type;
223
224 begin_bag(const argument_type& index) : inherited_t(begin_bag::fct, index) {}
225
226 inherited_t& operator()(argument_type /*i*/) { return *this; }
227
228private:
229 static stream_type& fct(stream_type& os, const argument_type& i) {
230 format_base* format(get_formatter(os));
231
232 if (format)
233 format->begin_bag(os, i);
234
235 return os;
236 }
237};
238
239/**************************************************************************************************/
240
242template <typename T>
243class begin_atom : public basic_omanipulator<const serializable_t, char, std::char_traits<char>> {
244 typedef basic_omanipulator<const serializable_t, char, std::char_traits<char>> inherited_t;
245
246public:
247 typedef inherited_t::stream_type stream_type;
248 typedef inherited_t::argument_type argument_type;
249
250 explicit begin_atom(const T& x) : inherited_t(begin_atom::fct, serializable_t(x)) {}
251
252 inherited_t& operator()(argument_type /*i*/) { return *this; }
253
254private:
255 static stream_type& fct(stream_type& os, const argument_type& atom) {
256 format_base* format(get_formatter(os));
257
258 if (format)
259 format->begin_atom(os, atom);
260 else
261 os << atom;
262
263 return os;
264 }
265};
266
267/**************************************************************************************************/
268
270template <typename T, class charT, class traits>
271std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os,
272 const begin_atom<T>& manip) {
273 if (os.good())
274 manip.do_manip(os);
275
276 return os;
277}
278
279/**************************************************************************************************/
280
282template <typename NewFormat>
283void callback(std::ios_base::event ev, std::ios_base& strm, int idx) {
284 if (ev == std::ios_base::erase_event) {
285 try {
286 delete static_cast<NewFormat*>(strm.pword(idx));
287
288 strm.pword(idx) = 0;
289 } catch (...) {
290 }
291 } else if (ev == std::ios_base::copyfmt_event) {
292 NewFormat* old(static_cast<NewFormat*>(strm.pword(idx)));
293
294 if (old != 0) {
295 try {
296 strm.pword(idx) = new NewFormat(*old);
297 } catch (std::bad_alloc&) {
298 }
299 }
300 }
301}
302
303/**************************************************************************************************/
304
306template <typename OldFormat, typename NewFormat>
307void replace_pword(std::ios_base& iob, int idx) {
308 iob.register_callback(callback<NewFormat>, idx);
309
310 NewFormat* new_format(new NewFormat());
311 OldFormat* old_format(static_cast<OldFormat*>(iob.pword(idx)));
312 iob.pword(idx) = new_format;
313 delete old_format;
314}
315
316/**************************************************************************************************/
317
319template <typename OldFormat, typename NewFormat, typename T>
320void replace_pword(std::ios_base& iob, int idx, const T& x) {
321 iob.register_callback(callback<NewFormat>, idx);
322
323 NewFormat* new_format(new NewFormat(x));
324 OldFormat* old_format(static_cast<OldFormat*>(iob.pword(idx)));
325 iob.pword(idx) = new_format;
326 delete old_format;
327}
328
329/**************************************************************************************************/
330
332template <class T>
333std::ostream& fmt(std::ostream& os, const T& t) {
334 os << begin_atom<T>(t) << end_atom;
335
336 return os;
337}
338
339/**************************************************************************************************/
340
342template <class T>
343class basic_format : public basic_omanipulator<T, char, std::char_traits<char>> {
344 typedef basic_omanipulator<T, char, std::char_traits<char>> inherited_t;
345
346public:
347 typedef typename inherited_t::stream_type stream_type;
348 typedef typename inherited_t::argument_type argument_type;
349
350 basic_format(const argument_type& t) : inherited_t(fmt<T>, t) {}
351
352 inherited_t& operator()(const argument_type& /*i*/) { return *this; }
353};
354
355/**************************************************************************************************/
356
358template <class T>
359inline basic_format<T> format(const T& t) {
360 return basic_format<T>(t);
361}
362
363/**************************************************************************************************/
364
365} // namespace adobe
366
367/**************************************************************************************************/
368
369#endif
370
371/**************************************************************************************************/
372
373#endif
374
375/**************************************************************************************************/
boost::range_difference< InputRange >::type count(InputRange &range, T &value)
count implementation
Definition count.hpp:40
std::ostream & operator<<(std::ostream &s, const extents_t &x)
Utility wrapper to construct name_t with strings of static storage duration.
Definition name.hpp:135