iomanip.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /*************************************************************************************************/ 00008 00009 #ifdef ADOBE_STD_SERIALIZATION 00010 00011 /*************************************************************************************************/ 00012 00013 #ifndef ADOBE_IOMANIP_HPP 00014 #define ADOBE_IOMANIP_HPP 00015 00016 /*************************************************************************************************/ 00017 00018 #include <adobe/config.hpp> 00019 00020 #include <cassert> 00021 #include <iosfwd> 00022 #include <string> 00023 #include <sstream> 00024 #include <list> 00025 #include <stdexcept> 00026 #include <functional> 00027 00028 #include <adobe/any_regular.hpp> 00029 #include <adobe/iomanip_fwd.hpp> 00030 #include <adobe/manip.hpp> 00031 #include <adobe/name.hpp> 00032 00033 /*************************************************************************************************/ 00034 00035 namespace adobe { 00036 00037 /*************************************************************************************************/ 00038 00039 namespace implementation { 00040 00041 /*************************************************************************************************/ 00042 00043 } // namespace implementation 00044 00045 /*************************************************************************************************/ 00046 00047 static const aggregate_name_t bag_name_g = { "bag" }; 00048 static const aggregate_name_t seq_name_g = { "seq" }; 00049 static const aggregate_name_t alt_name_g = { "alt" }; 00050 static const aggregate_name_t atom_name_g = { "atom" }; 00051 00052 /*************************************************************************************************/ 00053 00059 00060 class format_element_t 00061 { 00062 public: 00063 explicit format_element_t(name_t tag = name_t(), 00064 const std::string& ident = std::string()) : 00065 ident_m(ident), 00066 num_out_m(0), 00067 tag_m(tag), 00068 value_m(0) 00069 { } 00070 00071 format_element_t(name_t tag, const any_regular_t& value) : 00072 num_out_m(0), 00073 tag_m(tag), 00074 value_m(&value) 00075 { } 00076 00077 name_t tag() const 00078 { return tag_m; } 00079 00080 const any_regular_t& value() const 00081 { 00082 if (!value_m) 00083 throw std::runtime_error("invalid value"); 00084 00085 return *value_m; 00086 } 00087 00088 std::string ident_m; 00089 std::size_t num_out_m; 00090 00091 private: 00092 name_t tag_m; 00093 const any_regular_t* value_m; 00094 }; 00095 00096 /*************************************************************************************************/ 00097 00099 class format_base 00100 { 00101 public: 00102 typedef std::ostream stream_type; 00103 typedef format_element_t stack_value_type; 00104 typedef std::list<stack_value_type> stack_type; 00105 00106 virtual ~format_base() 00107 { } 00108 00109 virtual void begin_format(stream_type& os) { push_stack(os); } 00110 virtual void end_format(stream_type& os) { pop_stack(os); } 00111 00112 virtual void begin_bag(stream_type& os, const std::string&) { push_stack(os); } 00113 virtual void end_bag(stream_type& os) { pop_stack(os); } 00114 00115 virtual void begin_sequence(stream_type& os) { push_stack(os); } 00116 virtual void end_sequence(stream_type& os) { pop_stack(os); } 00117 00118 virtual void begin_alternate(stream_type& os) { push_stack(os); } 00119 virtual void end_alternate(stream_type& os) { pop_stack(os); } 00120 00121 virtual void begin_atom(stream_type& os, const any_regular_t&) { push_stack(os); } 00122 virtual void end_atom(stream_type& os) { pop_stack(os); } 00123 00124 format_base() : 00125 depth_m(0) 00126 { } 00127 00128 virtual std::size_t depth() 00129 { return depth_m; } 00130 00131 virtual std::size_t stack_depth() 00132 { return stack_m.size(); } 00133 00134 protected: 00135 00136 void push_stack(stream_type& os, 00137 const stack_value_type& element = format_element_t()) 00138 { 00139 stack_m.push_front(element); 00140 stack_event(os, true); 00141 } 00142 00143 void pop_stack(stream_type& os) 00144 { 00145 assert(stack_m.empty() == false); 00146 stack_event(os, false); 00147 stack_m.pop_front(); 00148 } 00149 00150 const stack_value_type& stack_top() const 00151 { return stack_n(0); } 00152 00153 stack_value_type& stack_top() 00154 { return stack_n(0); } 00155 00156 const stack_value_type& stack_n(std::size_t n) const 00157 { 00158 if (n > stack_m.size()) 00159 { 00160 std::stringstream buf; 00161 buf << "stack_n: n(" << static_cast<unsigned int>(n) << ") > size(" << static_cast<unsigned int>(stack_m.size()) << ")."; 00162 throw std::range_error(buf.str()); 00163 } 00164 00165 return *boost::next(stack_m.begin(), n); 00166 } 00167 00168 stack_value_type& stack_n(std::size_t n) 00169 { 00170 if (n > stack_m.size()) 00171 { 00172 std::stringstream buf; 00173 buf << "stack_n: n(" << static_cast<unsigned int>(n) << ") > size(" << static_cast<unsigned int>(stack_m.size()) << ")."; 00174 throw std::range_error(buf.str()); 00175 } 00176 00177 return *boost::next(stack_m.begin(), n); 00178 } 00179 00180 void up() 00181 { ++depth_m; } 00182 00183 void down() 00184 { std::size_t temp = (std::max)(std::size_t(0), --depth_m); 00185 depth_m = temp; // use temp to suppress gcc-4.5.0 warning/error 00186 } 00187 00188 private: 00189 virtual void stack_event(stream_type& os, bool is_push) = 0; 00190 00191 std::size_t depth_m; // note: Visual "depth", NOT the depth of the stack 00192 stack_type stack_m; 00193 }; 00194 00195 /*************************************************************************************************/ 00196 00197 format_base::stream_type& begin_format(format_base::stream_type& os); 00198 format_base::stream_type& end_format(format_base::stream_type& os); 00199 00200 format_base::stream_type& end_bag(format_base::stream_type& os); 00201 00202 format_base::stream_type& begin_sequence(format_base::stream_type& os); 00203 format_base::stream_type& end_sequence(format_base::stream_type& os); 00204 00205 format_base::stream_type& begin_alternate(format_base::stream_type& os); 00206 format_base::stream_type& end_alternate(format_base::stream_type& os); 00207 00208 format_base::stream_type& end_atom(format_base::stream_type& os); 00209 00210 /*************************************************************************************************/ 00211 00213 class indents : public basic_omanipulator<std::size_t, char, std::char_traits<char> > 00214 { 00215 typedef basic_omanipulator<std::size_t, char, std::char_traits<char> > inherited_t; 00216 00217 public: 00218 typedef inherited_t::stream_type stream_type; 00219 typedef inherited_t::argument_type argument_type; 00220 00221 indents(argument_type num) : 00222 inherited_t(indents::fct, num) 00223 { } 00224 00225 inherited_t& operator() (argument_type i) 00226 { arg_m = i; return *this; } 00227 00228 private: 00229 static stream_type& fct(stream_type& os, const argument_type& i) 00230 { 00231 for (argument_type count(0); count < i; ++count) 00232 os.put('\t'); 00233 00234 return os; 00235 } 00236 }; 00237 00238 /*************************************************************************************************/ 00239 00241 class begin_bag : public basic_omanipulator<std::string, char, std::char_traits<char> > 00242 { 00243 typedef basic_omanipulator<std::string, char, std::char_traits<char> > inherited_t; 00244 00245 public: 00246 typedef inherited_t::stream_type stream_type; 00247 typedef inherited_t::argument_type argument_type; 00248 00249 begin_bag(const argument_type& index) : 00250 inherited_t(begin_bag::fct, index) 00251 { } 00252 00253 inherited_t& operator() (argument_type /*i*/) 00254 { return *this; } 00255 00256 private: 00257 static stream_type& fct(stream_type& os, const argument_type& i) 00258 { 00259 format_base* format(get_formatter(os)); 00260 if (format) format->begin_bag(os, i); 00261 return os; 00262 } 00263 }; 00264 00265 /*************************************************************************************************/ 00266 00268 template <typename T> 00269 class begin_atom : public basic_omanipulator<const any_regular_t, char, std::char_traits<char> > 00270 { 00271 typedef basic_omanipulator<const any_regular_t, char, std::char_traits<char> > inherited_t; 00272 00273 public: 00274 typedef inherited_t::stream_type stream_type; 00275 typedef inherited_t::argument_type argument_type; 00276 00277 explicit begin_atom(const T& x) : 00278 inherited_t(begin_atom::fct, any_regular_t(x)) 00279 { } 00280 00281 inherited_t& operator() (argument_type /*i*/) 00282 { return *this; } 00283 00284 private: 00285 static stream_type& fct(stream_type& os, const argument_type& atom) 00286 { 00287 format_base* format(get_formatter(os)); 00288 00289 if (format == 0) 00290 return os << atom.cast<typename promote<T>::type>(); 00291 00292 format->begin_atom(os, atom); 00293 00294 return os; 00295 } 00296 }; 00297 00298 /*************************************************************************************************/ 00299 00301 template <typename T, class charT, class traits> 00302 std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& os, 00303 const begin_atom<T>& manip) 00304 { 00305 if (os.good()) 00306 manip.do_manip(os); 00307 00308 return os; 00309 } 00310 00311 /*************************************************************************************************/ 00312 00314 template <typename NewFormat> 00315 void callback(std::ios_base::event ev, std::ios_base& strm, int idx) 00316 { 00317 if (ev == std::ios_base::erase_event) 00318 { 00319 try 00320 { 00321 delete static_cast<NewFormat*>(strm.pword(idx)); 00322 00323 strm.pword(idx) = 0; 00324 } 00325 catch (...) 00326 { } 00327 } 00328 else if (ev == std::ios_base::copyfmt_event) 00329 { 00330 NewFormat* old(static_cast<NewFormat*>(strm.pword(idx))); 00331 00332 if (old != 0) 00333 { 00334 try 00335 { 00336 strm.pword(idx) = new NewFormat(*old); 00337 } 00338 catch (std::bad_alloc&) 00339 { } 00340 } 00341 } 00342 } 00343 00344 /*************************************************************************************************/ 00345 00347 template <typename OldFormat, typename NewFormat> 00348 void replace_pword(std::ios_base& iob, int idx) 00349 { 00350 iob.register_callback(callback<NewFormat>, idx); 00351 00352 NewFormat* new_format(new NewFormat()); 00353 OldFormat* old_format(static_cast<OldFormat*>(iob.pword(idx))); 00354 iob.pword(idx) = new_format; 00355 delete old_format; 00356 } 00357 00358 /*************************************************************************************************/ 00359 00361 template <typename OldFormat, typename NewFormat, typename T> 00362 void replace_pword(std::ios_base& iob, int idx, const T& x) 00363 { 00364 iob.register_callback(callback<NewFormat>, idx); 00365 00366 NewFormat* new_format(new NewFormat(x)); 00367 OldFormat* old_format(static_cast<OldFormat*>(iob.pword(idx))); 00368 iob.pword(idx) = new_format; 00369 delete old_format; 00370 } 00371 00372 /*************************************************************************************************/ 00373 00375 template <class T> 00376 std::ostream& fmt(std::ostream& os, const T& t) 00377 { 00378 os << begin_atom<T>(t) << end_atom; 00379 00380 return os; 00381 } 00382 00383 /*************************************************************************************************/ 00384 00386 template <class T> 00387 class basic_format : public basic_omanipulator<T, char, std::char_traits<char> > 00388 { 00389 typedef basic_omanipulator<T, char, std::char_traits<char> > inherited_t; 00390 00391 public: 00392 typedef typename inherited_t::stream_type stream_type; 00393 typedef typename inherited_t::argument_type argument_type; 00394 00395 basic_format(const argument_type& t) : 00396 inherited_t(fmt<T>, t) 00397 { } 00398 00399 inherited_t& operator() (const argument_type& /*i*/) 00400 { return *this; } 00401 }; 00402 00403 /*************************************************************************************************/ 00404 00406 template <class T> 00407 inline basic_format<T> format(const T& t) 00408 { 00409 return basic_format<T>(t); 00410 } 00411 00412 /*************************************************************************************************/ 00413 00414 } // namespace adobe 00415 00416 /*************************************************************************************************/ 00417 00418 #endif 00419 00420 /*************************************************************************************************/ 00421 00422 #endif 00423 00424 /*************************************************************************************************/ |