X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=boost%2Fboost%2Fformat%2Ffeed_args.hpp;h=53243dccc8c2c64e1d2aedbb4ddf42fb47ece463;hb=c48091f33a773732fa6c789927e5833e44108d9d;hp=5a8870be80eaec08ea934f2519b5760ef02bca85;hpb=32d33742555ca04f2333ed7c685de3145caa1b97;p=lyx.git diff --git a/boost/boost/format/feed_args.hpp b/boost/boost/format/feed_args.hpp index 5a8870be80..53243dccc8 100644 --- a/boost/boost/format/feed_args.hpp +++ b/boost/boost/format/feed_args.hpp @@ -1,262 +1,274 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from RĂ¼diger Loos's format class -// and Karl Nelson's ofstream - // ---------------------------------------------------------------------------- -// feed_args.hpp : functions for processing each argument +// feed_args.hpp : functions for processing each argument // (feed, feed_manip, and distribute) // ---------------------------------------------------------------------------- +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- #ifndef BOOST_FORMAT_FEED_ARGS_HPP #define BOOST_FORMAT_FEED_ARGS_HPP -#include "boost/format/format_class.hpp" -#include "boost/format/group.hpp" +#include +#include +#include -#include "boost/format/msvc_disambiguater.hpp" -#include "boost/throw_exception.hpp" +#include +#include +#include namespace boost { namespace io { namespace detail { -namespace { - - template inline - void empty_buf(BOOST_IO_STD basic_ostringstream & os) { - static const std::basic_string emptyStr; - os.str(emptyStr); - } - template - void do_pad( std::basic_string & s, - std::streamsize w, - const Ch c, - std::ios_base::fmtflags f, - bool center) - // applies centered / left / right padding to the string s. - // Effects : string s is padded. - { - std::streamsize n=w-s.size(); - if(n<=0) { - return; - } - if(center) - { - s.reserve(w); // allocate once for the 2 inserts - const std::streamsize n1 = n /2, n0 = n - n1; - s.insert(s.begin(), n0, c); - s.append(n1, c); - } - else - { - if(f & std::ios_base::left) { - s.append(n, c); + template + void mk_str( std::basic_string & res, + const Ch * beg, + typename std::basic_string::size_type size, + std::streamsize w, + const Ch fill_char, + std::ios_base::fmtflags f, + const Ch prefix_space, // 0 if no space-padding + bool center) + // applies centered/left/right padding to the string [beg, beg+size[ + // Effects : the result is placed in res. + { + typedef typename std::basic_string::size_type size_type; + res.resize(0); + if(w<=0 || static_cast(w) <=size) { + // no need to pad. + res.reserve(size + !!prefix_space); + if(prefix_space) + res.append(1, prefix_space); + if (size) + res.append(beg, size); } - else { - s.insert(s.begin(), n, c); + else { + std::streamsize n=static_cast(w-size-!!prefix_space); + std::streamsize n_after = 0, n_before = 0; + res.reserve(static_cast(w)); // allocate once for the 2 inserts + if(center) + n_after = n/2, n_before = n - n_after; + else + if(f & std::ios_base::left) + n_after = n; + else + n_before = n; + // now make the res string : + if(n_before) res.append(static_cast(n_before), fill_char); + if(prefix_space) + res.append(1, prefix_space); + if (size) + res.append(beg, size); + if(n_after) res.append(static_cast(n_after), fill_char); } - } - } // -do_pad(..) + } // -mk_str(..) -#if BOOST_WORKAROUND( BOOST_MSVC, <= 1300) +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) // MSVC needs to be tricked to disambiguate this simple overload.. // the trick is in "boost/format/msvc_disambiguater.hpp" - template< class Ch, class Tr, class T> inline - void put_head( BOOST_IO_STD basic_ostream& os, const T& x ) { - disambiguater::put_head(os, x, 1L); - } - template< class Ch, class Tr, class T> inline - void put_last( BOOST_IO_STD basic_ostream& os, const T& x ) { - disambiguater::put_last(os, x, 1L); - } + template< class Ch, class Tr, class T> inline + void put_head (BOOST_IO_STD basic_ostream & os, const T& x ) { + disambiguater::put_head(os, x, 1L); + } + template< class Ch, class Tr, class T> inline + void put_last (BOOST_IO_STD basic_ostream & os, const T& x ) { + disambiguater::put_last(os, x, 1L); + } #else - template< class Ch, class Tr, class T> inline - void put_head(BOOST_IO_STD basic_ostream& , const T& ) { - } + template< class Ch, class Tr, class T> inline + void put_head (BOOST_IO_STD basic_ostream &, const T& ) { + } - template< class Ch, class Tr, class T> inline - void put_head( BOOST_IO_STD basic_ostream& os, const group1& x ) { - os << group_head(x.a1_); // send the first N-1 items, not the last - } + template< class Ch, class Tr, class T> inline + void put_head( BOOST_IO_STD basic_ostream & os, const group1& x ) { + os << group_head(x.a1_); // send the first N-1 items, not the last + } - template< class Ch, class Tr, class T> inline - void put_last( BOOST_IO_STD basic_ostream& os, const T& x ) { - os << x ; - } + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, const T& x ) { + os << x ; + } - template< class Ch, class Tr, class T> inline - void put_last( BOOST_IO_STD basic_ostream& os, const group1& x ) { - os << group_last(x.a1_); // this selects the last element - } + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, const group1& x ) { + os << group_last(x.a1_); // this selects the last element + } #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST - template< class Ch, class Tr, class T> inline - void put_head( BOOST_IO_STD basic_ostream& , T& ) { - } + template< class Ch, class Tr, class T> inline + void put_head( BOOST_IO_STD basic_ostream &, T& ) { + } - template< class Ch, class Tr, class T> inline - void put_last( BOOST_IO_STD basic_ostream& os, T& x ) { - os << x ; - } + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, T& x) { + os << x ; + } #endif #endif // -msvc workaround + template< class Ch, class Tr, class Alloc, class T> + void put( T x, + const format_item& specs, + typename basic_format::string_type& res, + typename basic_format::internal_streambuf_t & buf, + io::detail::locale_t *loc_p = NULL) + { +#ifdef BOOST_MSVC + // If std::min or std::max are already instantiated + // at this point then we get a blizzard of warning messages when we call + // those templates with std::size_t as arguments. Weird and very annoyning... +#pragma warning(push) +#pragma warning(disable:4267) +#endif + // does the actual conversion of x, with given params, into a string + // using the supplied stringbuf. - -template< class Ch, class Tr, class T> -void put( T x, - const format_item& specs, - std::basic_string & res, - BOOST_IO_STD basic_ostringstream& oss_ ) -{ - // does the actual conversion of x, with given params, into a string - // using the *supplied* strinstream. (the stream state is important) - - typedef std::basic_string string_t; - typedef format_item format_item_t; + typedef typename basic_format::string_type string_type; + typedef typename basic_format::format_item_t format_item_t; + typedef typename string_type::size_type size_type; - stream_format_state prev_state(oss_); - - specs.state_.apply_on(oss_); + basic_oaltstringstream oss( &buf); + specs.fmtstate_.apply_on(oss, loc_p); - // in case x is a group, apply the manip part of it, - // in order to find width - put_head( oss_, x ); - empty_buf( oss_); + // the stream format state can be modified by manipulators in the argument : + put_head( oss, x ); + // in case x is a group, apply the manip part of it, + // in order to find width - const std::streamsize w=oss_.width(); - const std::ios_base::fmtflags fl=oss_.flags(); - const bool internal = (fl & std::ios_base::internal) != 0; - const bool two_stepped_padding = internal - && ! ( specs.pad_scheme_ & format_item_t::spacepad ) - && specs.truncate_ < 0 ; + const std::ios_base::fmtflags fl=oss.flags(); + const bool internal = (fl & std::ios_base::internal) != 0; + const std::streamsize w = oss.width(); + const bool two_stepped_padding= internal && (w!=0); - - if(! two_stepped_padding) - { - if(w>0) // handle simple padding via do_pad, not natively in stream - oss_.width(0); - put_last( oss_, x); - res = oss_.str(); - - if (specs.truncate_ >= 0 && static_cast(specs.truncate_) < res.size() ) - res.erase(specs.truncate_); - - // complex pads : - if(specs.pad_scheme_ & format_item_t::spacepad) - { - if( res.size()==0 || ( res[0]!='+' && res[0]!='-' )) - { - res.insert(res.begin(), 1, ' '); // insert 1 space at pos 0 - } - } - if(w > 0) // need do_pad - { - do_pad(res,w,oss_.fill(), fl, (specs.pad_scheme_ & format_item_t::centered) !=0 ); + res.resize(0); + if(! two_stepped_padding) { + if(w>0) // handle padding via mk_str, not natively in stream + oss.width(0); + put_last( oss, x); + const Ch * res_beg = buf.pbase(); + Ch prefix_space = 0; + if(specs.pad_scheme_ & format_item_t::spacepad) + if(buf.pcount()== 0 || + (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) + prefix_space = oss.widen(' '); + size_type res_size = (std::min)( + static_cast(specs.truncate_ - !!prefix_space), + buf.pcount() ); + mk_str(res, res_beg, res_size, w, oss.fill(), fl, + prefix_space, (specs.pad_scheme_ & format_item_t::centered) !=0 ); } - } - else // 2-stepped padding - { - put_last( oss_, x); // oss_.width() may result in padding. - res = oss_.str(); - - if (specs.truncate_ >= 0) - res.erase(specs.truncate_); - - if( res.size() - w > 0) - { // length w exceeded - // either it was multi-output with first output padding up all width.. - // either it was one big arg and we are fine. - empty_buf( oss_); - oss_.width(0); - put_last(oss_, x ); - string_t tmp = oss_.str(); // minimal-length output - std::streamsize d; - if( (d=w - tmp.size()) <=0 ) - { - // minimal length is already >= w, so no padding (cool!) - res.swap(tmp); + else { // 2-stepped padding + // internal can be implied by zeropad, or user-set. + // left, right, and centered alignment overrule internal, + // but spacepad or truncate might be mixed with internal (using manipulator) + put_last( oss, x); // may pad + const Ch * res_beg = buf.pbase(); + size_type res_size = buf.pcount(); + bool prefix_space=false; + if(specs.pad_scheme_ & format_item_t::spacepad) + if(buf.pcount()== 0 || + (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) + prefix_space = true; + if(res_size == static_cast(w) && w<=specs.truncate_ && !prefix_space) { + // okay, only one thing was printed and padded, so res is fine + res.assign(res_beg, res_size); } - else - { // hum.. we need to pad (it was necessarily multi-output) - typedef typename string_t::size_type size_type; - size_type i = 0; - while( i( d ), oss_.fill()); - res.swap( tmp ); + else { // length w exceeded + // either it was multi-output with first output padding up all width.. + // either it was one big arg and we are fine. + // Note that res_size oss2( &buf); + specs.fmtstate_.apply_on(oss2, loc_p); + put_head( oss2, x ); + + oss2.width(0); + if(prefix_space) + oss2 << ' '; + put_last(oss2, x ); + if(buf.pcount()==0 && specs.pad_scheme_ & format_item_t::spacepad) { + prefix_space =true; + oss2 << ' '; + } + // we now have the minimal-length output + const Ch * tmp_beg = buf.pbase(); + size_type tmp_size = (std::min)(static_cast(specs.truncate_), + buf.pcount() ); + + + if(static_cast(w) <= tmp_size) { + // minimal length is already >= w, so no padding (cool!) + res.assign(tmp_beg, tmp_size); + } + else { // hum.. we need to pad (multi_output, or spacepad present) + //find where we should pad + size_type sz = (std::min)(res_size + (prefix_space ? 1 : 0), tmp_size); + size_type i = prefix_space; + for(; i=tmp_size) i=prefix_space; + res.assign(tmp_beg, i); + std::streamsize d = w - static_cast(tmp_size); + BOOST_ASSERT(d>0); + res.append(static_cast( d ), oss2.fill()); + res.append(tmp_beg+i, tmp_size-i); + BOOST_ASSERT(i+(tmp_size-i)+(std::max)(d,(std::streamsize)0) + == static_cast(w)); + BOOST_ASSERT(res.size() == static_cast(w)); + } } } - else - { // okay, only one thing was printed and padded, so res is fine. - } - } - - prev_state.apply_on(oss_); - empty_buf( oss_); - oss_.clear(); -} // end- put(..) - - -} // local namespace - - - + buf.clear_buffer(); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } // end- put(..) -template< class Ch, class Tr, class T> -void distribute(basic_format& self, T x) - // call put(x, ..) on every occurence of the current argument : -{ - if(self.cur_arg_ >= self.num_args_) - { - if( self.exceptions() & too_many_args_bit ) - boost::throw_exception(too_many_args()); // too many variables have been supplied ! - else return; - } - for(unsigned long i=0; i < self.items_.size(); ++i) - { - if(self.items_[i].argN_ == self.cur_arg_) - { - put (x, self.items_[i], self.items_[i].res_, self.oss_ ); + template< class Ch, class Tr, class Alloc, class T> + void distribute (basic_format& self, T x) { + // call put(x, ..) on every occurence of the current argument : + if(self.cur_arg_ >= self.num_args_) { + if( self.exceptions() & too_many_args_bit ) + boost::throw_exception(too_many_args(self.cur_arg_, self.num_args_)); + else return; + } + for(unsigned long i=0; i < self.items_.size(); ++i) { + if(self.items_[i].argN_ == self.cur_arg_) { + put (x, self.items_[i], self.items_[i].res_, + self.buf_, boost::get_pointer(self.loc_) ); + } } } -} -template -basic_format& feed(basic_format& self, T x) -{ - if(self.dumped_) self.clear(); - distribute (self, x); - ++self.cur_arg_; - if(self.bound_.size() != 0) - { - while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] ) + template + basic_format& + feed (basic_format& self, T x) { + if(self.dumped_) self.clear(); + distribute (self, x); ++self.cur_arg_; + if(self.bound_.size() != 0) { + while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] ) + ++self.cur_arg_; + } + return self; } - - // this arg is finished, reset the stream's format state - self.state0_.apply_on(self.oss_); - return self; -} - } // namespace detail } // namespace io } // namespace boost