Chris@16: // ---------------------------------------------------------------------------- Chris@16: // internals.hpp : internal structs : stream_format_state, format_item. Chris@16: // included by format.hpp Chris@16: // ---------------------------------------------------------------------------- Chris@16: Chris@16: // Copyright Samuel Krempp 2003. Use, modification, and distribution are Chris@16: // subject to the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/format for library home page Chris@16: Chris@16: // ---------------------------------------------------------------------------- Chris@16: Chris@16: #ifndef BOOST_FORMAT_INTERNALS_HPP Chris@16: #define BOOST_FORMAT_INTERNALS_HPP Chris@16: Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // used as a dummy stream Chris@16: Chris@16: namespace boost { Chris@16: namespace io { Chris@16: namespace detail { Chris@16: Chris@16: Chris@16: //---- stream_format_state --------------------------------------------------// Chris@16: Chris@16: // set of params that define the format state of a stream Chris@16: template Chris@16: struct stream_format_state Chris@16: { Chris@16: typedef BOOST_IO_STD basic_ios basic_ios; Chris@16: Chris@16: stream_format_state(Ch fill) { reset(fill); } Chris@16: // stream_format_state(const basic_ios& os) { set_by_stream(os); } Chris@16: Chris@16: void reset(Ch fill); //- sets to default state. Chris@16: void set_by_stream(const basic_ios& os); //- sets to os's state. Chris@16: void apply_on(basic_ios & os, //- applies format_state to the stream Chris@16: boost::io::detail::locale_t * loc_default = 0) const; Chris@16: template Chris@16: void apply_manip(T manipulator) //- modifies state by applying manipulator Chris@16: { apply_manip_body( *this, manipulator) ; } Chris@16: Chris@16: // --- data --- Chris@16: std::streamsize width_; Chris@16: std::streamsize precision_; Chris@16: Ch fill_; Chris@16: std::ios_base::fmtflags flags_; Chris@16: std::ios_base::iostate rdstate_; Chris@16: std::ios_base::iostate exceptions_; Chris@16: boost::optional loc_; Chris@16: }; Chris@16: Chris@16: Chris@16: //---- format_item ---------------------------------------------------------// Chris@16: Chris@16: // stores all parameters that can be specified in format strings Chris@16: template Chris@16: struct format_item Chris@16: { Chris@16: enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 }; Chris@16: // 1. if zeropad is set, all other bits are not, Chris@16: // 2. if tabulation is set, all others are not. Chris@16: // centered and spacepad can be mixed freely. Chris@16: enum arg_values { argN_no_posit = -1, // non-positional directive. will set argN later Chris@16: argN_tabulation = -2, // tabulation directive. (no argument read) Chris@16: argN_ignored = -3 // ignored directive. (no argument read) Chris@16: }; Chris@16: typedef BOOST_IO_STD basic_ios basic_ios; Chris@16: typedef detail::stream_format_state stream_format_state; Chris@16: typedef ::std::basic_string string_type; Chris@16: Chris@16: format_item(Ch fill) :argN_(argN_no_posit), fmtstate_(fill), Chris@16: truncate_(max_streamsize()), pad_scheme_(0) {} Chris@16: void reset(Ch fill); Chris@16: void compute_states(); // sets states according to truncate and pad_scheme. Chris@16: Chris@16: static std::streamsize max_streamsize() { Chris@16: return (std::numeric_limits::max)(); Chris@16: } Chris@16: Chris@16: // --- data --- Chris@16: int argN_; //- argument number (starts at 0, eg : %1 => argN=0) Chris@16: // negative values for items that don't process an argument Chris@16: string_type res_; //- result of the formatting of this item Chris@16: string_type appendix_; //- piece of string between this item and the next Chris@16: Chris@16: stream_format_state fmtstate_;// set by parsing, is only affected by modify_item Chris@16: Chris@16: std::streamsize truncate_;//- is set for directives like %.5s that ask truncation Chris@16: unsigned int pad_scheme_;//- several possible padding schemes can mix. see pad_values Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: //--- Definitions ------------------------------------------------------------ Chris@16: Chris@16: // - stream_format_state:: ------------------------------------------------- Chris@16: template Chris@16: void stream_format_state:: apply_on (basic_ios & os, Chris@16: boost::io::detail::locale_t * loc_default) const { Chris@101: // If a locale is available, set it first. "os.fill(fill_);" may chrash otherwise. Chris@101: #if !defined(BOOST_NO_STD_LOCALE) Chris@101: if(loc_) Chris@101: os.imbue(loc_.get()); Chris@101: else if(loc_default) Chris@101: os.imbue(*loc_default); Chris@101: #else Chris@101: (void) loc_default; // keep compiler quiet if we don't support locales Chris@101: #endif Chris@16: // set the state of this stream according to our params Chris@16: if(width_ != -1) Chris@16: os.width(width_); Chris@16: if(precision_ != -1) Chris@16: os.precision(precision_); Chris@16: if(fill_ != 0) Chris@16: os.fill(fill_); Chris@16: os.flags(flags_); Chris@16: os.clear(rdstate_); Chris@16: os.exceptions(exceptions_); Chris@16: } Chris@16: Chris@16: template Chris@16: void stream_format_state:: set_by_stream(const basic_ios& os) { Chris@16: // set our params according to the state of this stream Chris@16: flags_ = os.flags(); Chris@16: width_ = os.width(); Chris@16: precision_ = os.precision(); Chris@16: fill_ = os.fill(); Chris@16: rdstate_ = os.rdstate(); Chris@16: exceptions_ = os.exceptions(); Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: void apply_manip_body( stream_format_state& self, Chris@16: T manipulator) { Chris@16: // modify our params according to the manipulator Chris@16: basic_oaltstringstream ss; Chris@16: self.apply_on( ss ); Chris@16: ss << manipulator; Chris@16: self.set_by_stream( ss ); Chris@16: } Chris@16: Chris@16: template inline Chris@16: void stream_format_state:: reset(Ch fill) { Chris@16: // set our params to standard's default state. cf 27.4.4.1 of the C++ norm Chris@16: width_=0; precision_=6; Chris@16: fill_=fill; // default is widen(' '), but we cant compute it without the locale Chris@16: flags_ = std::ios_base::dec | std::ios_base::skipws; Chris@16: // the adjust_field part is left equal to 0, which means right. Chris@16: exceptions_ = std::ios_base::goodbit; Chris@16: rdstate_ = std::ios_base::goodbit; Chris@16: } Chris@16: Chris@16: Chris@16: // --- format_item:: -------------------------------------------------------- Chris@16: Chris@16: template Chris@16: void format_item:: Chris@16: reset (Ch fill) { Chris@16: argN_=argN_no_posit; truncate_ = max_streamsize(); pad_scheme_ =0; Chris@16: res_.resize(0); appendix_.resize(0); Chris@16: fmtstate_.reset(fill); Chris@16: } Chris@16: Chris@16: template Chris@16: void format_item:: Chris@16: compute_states() { Chris@16: // reflect pad_scheme_ on fmt_state_ Chris@16: // because some pad_schemes has complex consequences on several state params. Chris@16: if(pad_scheme_ & zeropad) { Chris@16: // ignore zeropad in left alignment : Chris@16: if(fmtstate_.flags_ & std::ios_base::left) { Chris@16: BOOST_ASSERT(!(fmtstate_.flags_ &(std::ios_base::adjustfield ^std::ios_base::left))); Chris@16: // only left bit might be set. (not right, nor internal) Chris@16: pad_scheme_ = pad_scheme_ & (~zeropad); Chris@16: } Chris@16: else { Chris@16: pad_scheme_ &= ~spacepad; // printf ignores spacepad when zeropadding Chris@16: fmtstate_.fill_='0'; Chris@16: fmtstate_.flags_ = (fmtstate_.flags_ & ~std::ios_base::adjustfield) Chris@16: | std::ios_base::internal; Chris@16: // removes all adjustfield bits, and adds internal. Chris@16: } Chris@16: } Chris@16: if(pad_scheme_ & spacepad) { Chris@16: if(fmtstate_.flags_ & std::ios_base::showpos) Chris@16: pad_scheme_ &= ~spacepad; Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: } } } // namespaces boost :: io :: detail Chris@16: Chris@16: Chris@16: #endif // BOOST_FORMAT_INTERNALS_HPP