diff options
Diffstat (limited to 'src/boost/format/parsing.cc')
-rw-r--r-- | src/boost/format/parsing.cc | 454 |
1 files changed, 0 insertions, 454 deletions
diff --git a/src/boost/format/parsing.cc b/src/boost/format/parsing.cc deleted file mode 100644 index 34c36adeb..000000000 --- a/src/boost/format/parsing.cc +++ /dev/null @@ -1,454 +0,0 @@ -// -*- 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 Rudiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// parsing.hpp : implementation of the parsing member functions -// ( parse, parse_printf_directive) -// ------------------------------------------------------------------------------ - - -#ifndef BOOST_FORMAT_PARSING_HPP -#define BOOST_FORMAT_PARSING_HPP - - -#include <boost/format.hpp> -#include <boost/throw_exception.hpp> -#include <boost/assert.hpp> - - -namespace boost { -namespace io { -namespace detail { - - template<class Stream> inline - bool wrap_isdigit(char c, Stream &os) - { -#ifndef BOOST_NO_LOCALE_ISIDIGIT - return std::isdigit(c, os.rdbuf()->getloc() ); -# else - using namespace std; - return isdigit(c); -#endif - } //end- wrap_isdigit(..) - - template<class Res> inline - Res str2int(const std::string& s, - std::string::size_type start, - BOOST_IO_STD ios &os, - const Res = Res(0) ) - // Input : char string, with starting index - // a basic_ios& merely to call its widen/narrow member function in the desired locale. - // Effects : reads s[start:] and converts digits into an integral n, of type Res - // Returns : n - { - Res n = 0; - while(start<s.size() && wrap_isdigit(s[start], os) ) { - char cur_ch = s[start]; - BOOST_ASSERT(cur_ch != 0 ); // since we called isdigit, this should not happen. - n *= 10; - n += cur_ch - '0'; // 22.2.1.1.2 of the C++ standard - ++start; - } - return n; - } - - void skip_asterisk(const std::string & buf, - std::string::size_type * pos_p, - BOOST_IO_STD ios &os) - // skip printf's "asterisk-fields" directives in the format-string buf - // Input : char string, with starting index *pos_p - // a basic_ios& merely to call its widen/narrow member function in the desired locale. - // Effects : advance *pos_p by skipping printf's asterisk fields. - // Returns : nothing - { - using namespace std; - BOOST_ASSERT( pos_p != 0); - if(*pos_p >= buf.size() ) return; - if(buf[ *pos_p]=='*') { - ++ (*pos_p); - while (*pos_p < buf.size() && wrap_isdigit(buf[*pos_p],os)) ++(*pos_p); - if(buf[*pos_p]=='$') ++(*pos_p); - } - } - - - inline void maybe_throw_exception( unsigned char exceptions) - // auxiliary func called by parse_printf_directive - // for centralising error handling - // it either throws if user sets the corresponding flag, or does nothing. - { - if(exceptions & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); - } - - - - bool parse_printf_directive(const std::string & buf, - std::string::size_type * pos_p, - detail::format_item * fpar, - BOOST_IO_STD ios &os, - unsigned char exceptions) - // Input : a 'printf-directive' in the format-string, starting at buf[ *pos_p ] - // a basic_ios& merely to call its widen/narrow member function in the desired locale. - // a bitset'excpetions' telling whether to throw exceptions on errors. - // Returns : true if parse somehow succeeded (possibly ignoring errors if exceptions disabled) - // false if it failed so bad that the directive should be printed verbatim - // Effects : - *pos_p is incremented so that buf[*pos_p] is the first char after the directive - // - *fpar is set with the parameters read in the directive - { - typedef format_item format_item_t; - BOOST_ASSERT( pos_p != 0); - std::string::size_type &i1 = *pos_p, - i0; - fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive - - bool in_brackets=false; - if(buf[i1]=='|') - { - in_brackets=true; - if( ++i1 >= buf.size() ) { - maybe_throw_exception(exceptions); - return false; - } - } - - // the flag '0' would be picked as a digit for argument order, but here it's a flag : - if(buf[i1]=='0') - goto parse_flags; - - // handle argument order (%2$d) or possibly width specification: %2d - i0 = i1; // save position before digits - while (i1 < buf.size() && wrap_isdigit(buf[i1], os)) - ++i1; - if (i1!=i0) - { - if( i1 >= buf.size() ) { - maybe_throw_exception(exceptions); - return false; - } - int n=str2int(buf,i0, os, int(0) ); - - // %N% case : this is already the end of the directive - if( buf[i1] == '%' ) - { - fpar->argN_ = n-1; - ++i1; - if( in_brackets) - maybe_throw_exception(exceptions); - // but don't return. maybe "%" was used in lieu of '$', so we go on. - else return true; - } - - if ( buf[i1]=='$' ) - { - fpar->argN_ = n-1; - ++i1; - } - else - { - // non-positionnal directive - fpar->ref_state_.width_ = n; - fpar->argN_ = format_item_t::argN_no_posit; - goto parse_precision; - } - } - - parse_flags: - // handle flags - while ( i1 <buf.size()) // as long as char is one of + - = # 0 l h or ' ' - { - // misc switches - switch (buf[i1]) - { - case '\'' : break; // no effect yet. (painful to implement) - case 'l': - case 'h': // short/long modifier : for printf-comaptibility (no action needed) - break; - case '-': - fpar->ref_state_.flags_ |= std::ios::left; - break; - case '=': - fpar->pad_scheme_ |= format_item_t::centered; - break; - case ' ': - fpar->pad_scheme_ |= format_item_t::spacepad; - break; - case '+': - fpar->ref_state_.flags_ |= std::ios::showpos; - break; - case '0': - fpar->pad_scheme_ |= format_item_t::zeropad; - // need to know alignment before really setting flags, - // so just add 'zeropad' flag for now, it will be processed later. - break; - case '#': - fpar->ref_state_.flags_ |= std::ios::showpoint | std::ios::showbase; - break; - default: - goto parse_width; - } - ++i1; - } // loop on flag. - if( i1>=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - - parse_width: - // handle width spec - skip_asterisk(buf, &i1, os); // skips 'asterisk fields' : *, or *N$ - i0 = i1; // save position before digits - while (i1<buf.size() && wrap_isdigit(buf[i1], os)) - i1++; - - if (i1!=i0) - { fpar->ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); } - - parse_precision: - if( i1>=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - // handle precision spec - if (buf[i1]=='.') - { - ++i1; - skip_asterisk(buf, &i1, os); - i0 = i1; // save position before digits - while (i1<buf.size() && wrap_isdigit(buf[i1], os)) - ++i1; - - if(i1==i0) - fpar->ref_state_.precision_ = 0; - else - fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) ); - } - - // handle formatting-type flags : - while( i1<buf.size() && - ( buf[i1]=='l' || buf[i1]=='L' || buf[i1]=='h') ) - ++i1; - if( i1>=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - - if( in_brackets && buf[i1]=='|' ) - { - ++i1; - return true; - } - switch (buf[i1]) - { - case 'X': - fpar->ref_state_.flags_ |= std::ios::uppercase; - case 'p': // pointer => set hex. - case 'x': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::hex; - break; - - case 'o': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::oct; - break; - - case 'E': - fpar->ref_state_.flags_ |= std::ios::uppercase; - case 'e': - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - fpar->ref_state_.flags_ |= std::ios::scientific; - - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - break; - - case 'f': - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - fpar->ref_state_.flags_ |= std::ios::fixed; - case 'u': - case 'd': - case 'i': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - break; - - case 'T': - ++i1; - if( i1 >= buf.size()) - maybe_throw_exception(exceptions); - else - fpar->ref_state_.fill_ = buf[i1]; - fpar->pad_scheme_ |= format_item_t::tabulation; - fpar->argN_ = format_item_t::argN_tabulation; - break; - case 't': - fpar->ref_state_.fill_ = ' '; - fpar->pad_scheme_ |= format_item_t::tabulation; - fpar->argN_ = format_item_t::argN_tabulation; - break; - - case 'G': - fpar->ref_state_.flags_ |= std::ios::uppercase; - break; - case 'g': // 'g' conversion is default for floats. - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - - // CLEAR all floatield flags, so stream will CHOOSE - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - break; - - case 'C': - case 'c': - fpar->truncate_ = 1; - break; - case 'S': - case 's': - fpar->truncate_ = fpar->ref_state_.precision_; - fpar->ref_state_.precision_ = -1; - break; - case 'n' : - fpar->argN_ = format_item_t::argN_ignored; - break; - default: - maybe_throw_exception(exceptions); - } - ++i1; - - if( in_brackets ) - { - if( i1<buf.size() && buf[i1]=='|' ) - { - ++i1; - return true; - } - else maybe_throw_exception(exceptions); - } - return true; - } - -} // detail namespace -} // io namespace - - -// ----------------------------------------------- -// format :: parse(..) - -void basic_format::parse(const string_t & buf) - // parse the format-string -{ - using namespace std; - const char arg_mark = '%'; - bool ordered_args=true; - int max_argN=-1; - string_t::size_type i1=0; - int num_items=0; - - // A: find upper_bound on num_items and allocates arrays - i1=0; - while( (i1=buf.find(arg_mark,i1)) != string::npos ) - { - if( i1+1 >= buf.size() ) { - if(exceptions() & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); // must not end in "bla bla %" - else break; // stop there, ignore last '%' - } - if(buf[i1+1] == buf[i1] ) { i1+=2; continue; } // escaped "%%" / "##" - ++i1; - - // in case of %N% directives, dont count it double (wastes allocations..) : - while(i1 < buf.size() && io::detail::wrap_isdigit(buf[i1],oss_)) ++i1; - if( i1 < buf.size() && buf[i1] == arg_mark ) ++ i1; - - ++num_items; - } - items_.assign( num_items, format_item_t() ); - - // B: Now the real parsing of the format string : - num_items=0; - i1 = 0; - string_t::size_type i0 = i1; - bool special_things=false; - int cur_it=0; - while( (i1=buf.find(arg_mark,i1)) != string::npos ) - { - string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; - - if( buf[i1+1] == buf[i1] ) // escaped mark, '%%' - { - piece += buf.substr(i0, i1-i0) + buf[i1]; - i1+=2; i0=i1; - continue; - } - BOOST_ASSERT( static_cast<unsigned int>(cur_it) < items_.size() || cur_it==0); - - if(i1!=i0) piece += buf.substr(i0, i1-i0); - ++i1; - - bool parse_ok; - parse_ok = io::detail::parse_printf_directive(buf, &i1, &items_[cur_it], oss_, exceptions()); - if( ! parse_ok ) continue; // the directive will be printed verbatim - - i0=i1; - items_[cur_it].compute_states(); // process complex options, like zeropad, into stream params. - - int argN=items_[cur_it].argN_; - if(argN == format_item_t::argN_ignored) - continue; - if(argN ==format_item_t::argN_no_posit) - ordered_args=false; - else if(argN == format_item_t::argN_tabulation) special_things=true; - else if(argN > max_argN) max_argN = argN; - ++num_items; - ++cur_it; - } // loop on %'s - BOOST_ASSERT(cur_it == num_items); - - // store the final piece of string - string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; - piece += buf.substr(i0); - - if( !ordered_args) - { - if(max_argN >= 0 ) // dont mix positional with non-positionnal directives - { - if(exceptions() & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); - // else do nothing. => positionnal arguments are processed as non-positionnal - } - // set things like it would have been with positional directives : - int non_ordered_items = 0; - for(int i=0; i< num_items; ++i) - if(items_[i].argN_ == format_item_t::argN_no_posit) - { - items_[i].argN_ = non_ordered_items; - ++non_ordered_items; - } - max_argN = non_ordered_items-1; - } - - // C: set some member data : - items_.resize(num_items); - - if(special_things) style_ |= special_needs; - num_args_ = max_argN + 1; - if(ordered_args) style_ |= ordered; - else style_ &= ~ordered; -} - -} // namespace boost - - -#endif // BOOST_FORMAT_PARSING_HPP |