-// -*- 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
-
// ----------------------------------------------------------------------------
// format_implementation.hpp Implementation of the basic_format class
// ----------------------------------------------------------------------------
+// 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_IMPLEMENTATION_HPP
#define BOOST_FORMAT_IMPLEMENTATION_HPP
+#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/format/format_class.hpp>
namespace boost {
-// -------- format:: -------------------------------------------
- template< class Ch, class Tr>
- basic_format<Ch, Tr>:: basic_format(const Ch* str)
+// --- basic_format implementation -----------------------------------------//
+
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* s)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
exceptions_(io::all_error_bits)
{
- if( str)
- parse( str );
+ if( s)
+ parse( s );
}
-#ifndef BOOST_NO_STD_LOCALE
- template< class Ch, class Tr>
- basic_format<Ch, Tr>:: basic_format(const Ch* str, const std::locale & loc)
+#if !defined(BOOST_NO_STD_LOCALE)
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch, Tr, Alloc>:: basic_format(const Ch* s, const std::locale & loc)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
- exceptions_(io::all_error_bits)
+ loc_(loc), exceptions_(io::all_error_bits)
{
- oss_.imbue( loc );
- if(str) parse( str );
+ if(s) parse( s );
}
- template< class Ch, class Tr>
- basic_format<Ch, Tr>:: basic_format(const string_t& s, const std::locale & loc)
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s, const std::locale & loc)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
- exceptions_(io::all_error_bits)
+ loc_(loc), exceptions_(io::all_error_bits)
{
- oss_.imbue( loc );
parse(s);
}
-#endif //BOOST_NO_STD_LOCALE
+#endif // ! BOOST_NO_STD_LOCALE
+ template< class Ch, class Tr, class Alloc>
+ io::detail::locale_t basic_format<Ch, Tr, Alloc>::
+ getloc() const {
+ return loc_ ? loc_.get() : io::detail::locale_t();
+ }
- template< class Ch, class Tr>
- basic_format<Ch, Tr>:: basic_format(const string_t& s)
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch, Tr, Alloc>:: basic_format(const string_type& s)
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
exceptions_(io::all_error_bits)
{
parse(s);
}
- template< class Ch, class Tr>
- basic_format<Ch, Tr>:: basic_format(const basic_format& x)
- : items_(x.items_), bound_(x.bound_), style_(x.style_),
- cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false),
- prefix_(x.prefix_), exceptions_(x.exceptions_)
- {
- }
+ template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member
+ basic_format<Ch, Tr, Alloc>:: basic_format(const basic_format& x)
+ : items_(x.items_), bound_(x.bound_), style_(x.style_),
+ cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false),
+ prefix_(x.prefix_), exceptions_(x.exceptions_), loc_(x.loc_)
+ {
+ }
- template< class Ch, class Tr>
- void basic_format<Ch, Tr>:: swap (basic_format & x) {
+ template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member
+ basic_format<Ch, Tr, Alloc>& basic_format<Ch, Tr, Alloc>::
+ operator= (const basic_format& x) {
+ if(this == &x)
+ return *this;
+ (basic_format<Ch, Tr, Alloc>(x)).swap(*this);
+ return *this;
+ }
+ template< class Ch, class Tr, class Alloc>
+ void basic_format<Ch, Tr, Alloc>::
+ swap (basic_format & x) {
std::swap(exceptions_, x.exceptions_);
std::swap(style_, x.style_);
std::swap(cur_arg_, x.cur_arg_);
bound_.swap(x.bound_);
}
- template< class Ch, class Tr>
- basic_format<Ch, Tr>& basic_format<Ch, Tr>:: operator= (const basic_format& x) {
- if(this == &x)
- return *this;
- (basic_format<Ch, Tr>(x)).swap(*this);
- return *this;
- }
-
- template< class Ch, class Tr>
- unsigned char basic_format<Ch,Tr>:: exceptions() const {
+ template< class Ch, class Tr, class Alloc>
+ unsigned char basic_format<Ch,Tr, Alloc>:: exceptions() const {
return exceptions_;
}
- template< class Ch, class Tr>
- unsigned char basic_format<Ch,Tr>:: exceptions(unsigned char newexcept) {
+ template< class Ch, class Tr, class Alloc>
+ unsigned char basic_format<Ch,Tr, Alloc>:: exceptions(unsigned char newexcept) {
unsigned char swp = exceptions_;
exceptions_ = newexcept;
return swp;
}
- template<class Ch, class Tr>
- void basic_format<Ch, Tr>:: make_or_reuse_data(std::size_t nbitems) {
- Ch fill = oss_.widen(' ');
+ template<class Ch, class Tr, class Alloc>
+ void basic_format<Ch, Tr, Alloc>::
+ make_or_reuse_data (std::size_t nbitems) {
+#if !defined(BOOST_NO_STD_LOCALE)
+ Ch fill = ( BOOST_USE_FACET(std::ctype<Ch>, getloc()) ). widen(' ');
+#else
+ Ch fill = ' ';
+#endif
if(items_.size() == 0)
items_.assign( nbitems, format_item_t(fill) );
else {
+ if(nbitems>items_.size())
+ items_.resize(nbitems, format_item_t(fill));
bound_.resize(0);
- items_.resize(nbitems, format_item_t(fill));
for(std::size_t i=0; i < nbitems; ++i)
- items_[i].reset(fill); // strings are resized to "", instead of reallocated
+ items_[i].reset(fill); // strings are resized, instead of reallocated
}
+ prefix_.resize(0);
}
- template< class Ch, class Tr>
- basic_format<Ch,Tr>& basic_format<Ch,Tr>:: clear() {
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
+ clear () {
// empty the string buffers (except bound arguments)
// and make the format object ready for formatting a new set of arguments
for(unsigned long i=0; i<items_.size(); ++i) {
// clear converted strings only if the corresponding argument is not bound :
- if( bound_.size()==0 || !bound_[ items_[i].argN_ ] ) items_[i].res_.resize(0);
+ if( bound_.size()==0 || items_[i].argN_<0 || !bound_[ items_[i].argN_ ] )
+ items_[i].res_.resize(0);
}
cur_arg_=0; dumped_=false;
// maybe first arg is bound:
if(bound_.size() != 0) {
- while(cur_arg_ < num_args_ && bound_[cur_arg_] )
- ++cur_arg_;
+ for(; cur_arg_ < num_args_ && bound_[cur_arg_]; ++cur_arg_)
+ {}
}
return *this;
}
- template< class Ch, class Tr>
- basic_format<Ch,Tr>& basic_format<Ch,Tr>:: clear_binds() {
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
+ clear_binds () {
// remove all binds, then clear()
bound_.resize(0);
clear();
return *this;
}
- template< class Ch, class Tr>
- basic_format<Ch,Tr>& basic_format<Ch,Tr>:: clear_bind(int argN) {
+ template< class Ch, class Tr, class Alloc>
+ basic_format<Ch,Tr, Alloc>& basic_format<Ch,Tr, Alloc>::
+ clear_bind (int argN) {
// remove the bind of ONE argument then clear()
-
if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) {
- if( exceptions() & io::out_of_range_bit )
- boost::throw_exception(io::out_of_range()); // arg not in range.
+ if( exceptions() & io::out_of_range_bit)
+ boost::throw_exception(io::out_of_range(argN, 1, num_args_+1 ) );
else return *this;
}
bound_[argN-1]=false;
return *this;
}
-
-
- template< class Ch, class Tr>
- std::basic_string<Ch,Tr> basic_format<Ch,Tr>:: str() const {
- dumped_=true;
+ template< class Ch, class Tr, class Alloc>
+ typename basic_format<Ch, Tr, Alloc>::string_type
+ basic_format<Ch,Tr, Alloc>::
+ str () const {
if(items_.size()==0)
return prefix_;
if( cur_arg_ < num_args_)
if( exceptions() & io::too_few_args_bit )
- boost::throw_exception(io::too_few_args()); // not enough variables supplied
+ // not enough variables supplied
+ boost::throw_exception(io::too_few_args(cur_arg_, num_args_));
+
unsigned long i;
- string_t res;
+ string_type res;
res.reserve(size());
res += prefix_;
for(i=0; i < items_.size(); ++i) {
res += item.res_;
if( item.argN_ == format_item_t::argN_tabulation) {
BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
- std::streamsize n = item.fmtstate_.width_ - res.size();
- if( n > 0 )
- res.append( n, item.fmtstate_.fill_ );
+ if( static_cast<size_type>(item.fmtstate_.width_) > res.size() )
+ res.append( static_cast<size_type>(item.fmtstate_.width_) - res.size(),
+ item.fmtstate_.fill_ );
}
res += item.appendix_;
}
+ dumped_=true;
return res;
}
- template< class Ch, class Tr>
- typename basic_format<Ch, Tr>::size_type basic_format<Ch,Tr>::
+ template< class Ch, class Tr, class Alloc>
+ typename std::basic_string<Ch, Tr, Alloc>::size_type basic_format<Ch,Tr, Alloc>::
size () const {
- std::streamsize sz = prefix_.size();
+#ifdef BOOST_MSVC
+ // If std::min<unsigned> or std::max<unsigned> 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
+ BOOST_USING_STD_MAX();
+ size_type sz = prefix_.size();
unsigned long i;
for(i=0; i < items_.size(); ++i) {
const format_item_t& item = items_[i];
sz += item.res_.size();
if( item.argN_ == format_item_t::argN_tabulation)
- sz = std::max(sz, item.fmtstate_.width_);
- sz += + item.appendix_.size();
+ sz = max BOOST_PREVENT_MACRO_SUBSTITUTION (sz,
+ static_cast<size_type>(item.fmtstate_.width_) );
+ sz += item.appendix_.size();
}
- return static_cast<size_type> (sz);
+ return sz;
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
}
namespace io {
namespace detail {
- template<class Ch, class Tr, class T>
- basic_format<Ch, Tr>& bind_arg_body( basic_format<Ch, Tr>& self,
- int argN, const T& val) {
+ template<class Ch, class Tr, class Alloc, class T>
+ basic_format<Ch, Tr, Alloc>&
+ bind_arg_body (basic_format<Ch, Tr, Alloc>& self, int argN, const T& val) {
// bind one argument to a fixed value
// this is persistent over clear() calls, thus also over str() and <<
if(self.dumped_)
self.clear(); // needed because we will modify cur_arg_
if(argN<1 || argN > self.num_args_) {
if( self.exceptions() & io::out_of_range_bit )
- boost::throw_exception(io::out_of_range()); // arg not in range.
+ boost::throw_exception(io::out_of_range(argN, 1, self.num_args_+1 ) );
else return self;
}
if(self.bound_.size()==0)
return self;
}
- template<class Ch, class Tr, class T>
- basic_format<Ch, Tr>& modify_item_body( basic_format<Ch, Tr>& self,
- int itemN, T manipulator) {
+ template<class Ch, class Tr, class Alloc, class T> basic_format<Ch, Tr, Alloc>&
+ modify_item_body (basic_format<Ch, Tr, Alloc>& self, int itemN, T manipulator) {
// applies a manipulator to the format_item describing a given directive.
// this is a permanent change, clear or reset won't cancel that.
if(itemN<1 || itemN > static_cast<signed int>(self.items_.size() )) {
if( self.exceptions() & io::out_of_range_bit )
- boost::throw_exception(io::out_of_range()); // item not in range.
+ boost::throw_exception(io::out_of_range(itemN, 1, static_cast<int>(self.items_.size()) ));
else return self;
}
self.items_[itemN-1].fmtstate_. template apply_manip<T> ( manipulator );