📄 parsing.hpp
字号:
// ----------------------------------------------------------------------------// parsing.hpp : implementation of the parsing member functions// ( parse, parse_printf_directive)// ----------------------------------------------------------------------------// 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_PARSING_HPP#define BOOST_FORMAT_PARSING_HPP#include <boost/format/format_class.hpp>#include <boost/throw_exception.hpp>#include <boost/assert.hpp>namespace boost {namespace io {namespace detail {#if defined(BOOST_NO_STD_LOCALE) // streams will be used for narrow / widen. but these methods are not const template<class T> T& const_or_not(const T& x) { return const_cast<T&> (x); }#else template<class T> const T& const_or_not(const T& x) { return x; }#endif template<class Ch, class Facet> inline char wrap_narrow(const Facet& fac, Ch c, char deflt) { return const_or_not(fac).narrow(c, deflt); } template<class Ch, class Facet> inline bool wrap_isdigit(const Facet& fac, Ch c) {#if ! defined( BOOST_NO_LOCALE_ISIDIGIT ) return fac.is(std::ctype<Ch>::digit, c);# else using namespace std; return isdigit(c); #endif } template<class Iter, class Facet> Iter wrap_scan_notdigit(const Facet & fac, Iter beg, Iter end) { using namespace std; for( ; beg!=end && wrap_isdigit(fac, *beg); ++beg) ; return beg; } // Input : [start, last) iterators range and a // a Facet to use its widen/narrow member function // Effects : read sequence and convert digits into integral n, of type Res // Returns : n template<class Res, class Iter, class Facet> Iter str2int (const Iter & start, const Iter & last, Res & res, const Facet& fac) { using namespace std; Iter it; res=0; for(it=start; it != last && wrap_isdigit(fac, *it); ++it ) { char cur_ch = wrap_narrow(fac, *it, 0); // cant fail. res *= 10; res += cur_ch - '0'; // 22.2.1.1.2.13 of the C++ standard } return it; } // skip printf's "asterisk-fields" directives in the format-string buf // Input : char string, with starting index *pos_p // a Facet merely to use its widen/narrow member function // Effects : advance *pos_p by skipping printf's asterisk fields. // Returns : nothing template<class Iter, class Facet> Iter skip_asterisk(Iter start, Iter last, const Facet& fac) { using namespace std; ++ start; start = wrap_scan_notdigit(fac, start, last); if(start!=last && *start== const_or_not(fac).widen( '$') ) ++start; return start; } // auxiliary func called by parse_printf_directive // for centralising error handling // it either throws if user sets the corresponding flag, or does nothing. inline void maybe_throw_exception(unsigned char exceptions, std::size_t pos, std::size_t size) { if(exceptions & io::bad_format_string_bit) boost::throw_exception(io::bad_format_string(pos, size) ); } // Input: the position of a printf-directive in the format-string // a basic_ios& merely to use its widen/narrow member function // a bitset'exceptions' telling whether to throw exceptions on errors. // Returns: // true if parse succeeded (ignore some errors if exceptions disabled) // false if it failed so bad that the directive should be printed verbatim // Effects: // start is incremented so that *start is the first char after // this directive // *fpar is set with the parameters read in the directive template<class Ch, class Tr, class Alloc, class Iter, class Facet> bool parse_printf_directive(Iter & start, const Iter& last, detail::format_item<Ch, Tr, Alloc> * fpar, const Facet& fac, std::size_t offset, unsigned char exceptions) { typedef typename basic_format<Ch, Tr, Alloc>::format_item_t format_item_t; fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive bool precision_set = false; bool in_brackets=false; Iter start0 = start; std::size_t fstring_size = last-start0+offset; if(*start== const_or_not(fac).widen( '|')) { in_brackets=true; if( ++start >= last ) { maybe_throw_exception(exceptions, start-start0 + offset, fstring_size); return false; } } // the flag '0' would be picked as a digit for argument order, but here it's a flag : if(*start== const_or_not(fac).widen( '0')) goto parse_flags; // handle argument order (%2$d) or possibly width specification: %2d if(wrap_isdigit(fac, *start)) { int n; start = str2int(start, last, n, fac); if( start >= last ) { maybe_throw_exception(exceptions, start-start0+offset, fstring_size); return false; } // %N% case : this is already the end of the directive if( *start == const_or_not(fac).widen( '%') ) { fpar->argN_ = n-1; ++start; if( in_brackets) maybe_throw_exception(exceptions, start-start0+offset, fstring_size); // but don't return. maybe "%" was used in lieu of '$', so we go on. else return true; } if ( *start== const_or_not(fac).widen( '$') ) { fpar->argN_ = n-1; ++start; } else { // non-positionnal directive fpar->fmtstate_.width_ = n; fpar->argN_ = format_item_t::argN_no_posit; goto parse_precision; } } parse_flags: // handle flags while ( start != last) { // as long as char is one of + - = _ # 0 l h or ' ' // misc switches switch ( wrap_narrow(fac, *start, 0)) { case '\'' : break; // no effect yet. (painful to implement) case 'l': case 'h': // short/long modifier : for printf-comaptibility (no action needed) break; case '-': fpar->fmtstate_.flags_ |= std::ios_base::left; break; case '=': fpar->pad_scheme_ |= format_item_t::centered; break; case '_': fpar->fmtstate_.flags_ |= std::ios_base::internal; break; case ' ': fpar->pad_scheme_ |= format_item_t::spacepad; break; case '+': fpar->fmtstate_.flags_ |= std::ios_base::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->fmtstate_.flags_ |= std::ios_base::showpoint | std::ios_base::showbase; break; default: goto parse_width; } ++start; } // loop on flag. if( start>=last) { maybe_throw_exception(exceptions, start-start0+offset, fstring_size); return true; } parse_width: // handle width spec // first skip 'asterisk fields' : *, or *N$ if(*start == const_or_not(fac).widen( '*') ) start = skip_asterisk(start, last, fac); if(start!=last && wrap_isdigit(fac, *start)) start = str2int(start, last, fpar->fmtstate_.width_, fac); parse_precision: if( start>= last) { maybe_throw_exception(exceptions, start-start0+offset, fstring_size); return true; } // handle precision spec if (*start== const_or_not(fac).widen( '.')) { ++start; if(start != last && *start == const_or_not(fac).widen( '*') ) start = skip_asterisk(start, last, fac); if(start != last && wrap_isdigit(fac, *start)) { start = str2int(start, last, fpar->fmtstate_.precision_, fac); precision_set = true; } else fpar->fmtstate_.precision_ =0; } // handle formatting-type flags : while( start != last && ( *start== const_or_not(fac).widen( 'l')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -