stlab.adobe.com Adobe Systems Incorporated

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 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google