-template<class Ch, class Traits>
-void basic_format<Ch, Traits> ::parse(const string_t & buf)
- // parse the format-string
-{
- using namespace std;
- const Ch arg_mark = oss_.widen('%');
- bool ordered_args=true;
- int max_argN=-1;
- typename 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_t::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;
- typename string_t::size_type i0 = i1;
- bool special_things=false;
- int cur_it=0;
- while( (i1=buf.find(arg_mark,i1)) != string_t::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);
+ template<class Ch, class Tr, class Alloc>
+ basic_format<Ch, Tr, Alloc>& basic_format<Ch, Tr, Alloc>::
+ parse (const string_type& buf) {
+ // parse the format-string
+ using namespace std;
+#if !defined(BOOST_NO_STD_LOCALE)
+ const std::ctype<Ch> & fac = BOOST_USE_FACET( std::ctype<Ch>, getloc());
+#else
+ io::basic_oaltstringstream<Ch, Tr, Alloc> fac;
+ //has widen and narrow even on compilers without locale
+#endif
+
+ const Ch arg_mark = io::detail::const_or_not(fac).widen( '%');
+ bool ordered_args=true;
+ int max_argN=-1;
+
+ // A: find upper_bound on num_items and allocates arrays
+ int num_items = io::detail::upper_bound_from_fstring(buf, arg_mark, fac, exceptions());
+ make_or_reuse_data(num_items);
+
+ // B: Now the real parsing of the format string :
+ num_items=0;
+ typename string_type::size_type i0=0, i1=0;
+ typename string_type::const_iterator it;
+ bool special_things=false;
+ int cur_item=0;
+ while( (i1=buf.find(arg_mark,i1)) != string_type::npos ) {
+ string_type & piece = (cur_item==0) ? prefix_ : items_[cur_item-1].appendix_;
+ if( buf[i1+1] == buf[i1] ) { // escaped mark, '%%'
+ io::detail::append_string(piece, buf, i0, i1+1);
+ i1+=2; i0=i1;
+ continue;
+ }
+ BOOST_ASSERT( static_cast<unsigned int>(cur_item) < items_.size() || cur_item==0);
+
+ if(i1!=i0) {
+ io::detail::append_string(piece, buf, i0, i1);
+ i0=i1;
+ }
+ ++i1;
+ it = buf.begin()+i1;
+ bool parse_ok = io::detail::parse_printf_directive(
+ it, buf.end(), &items_[cur_item], fac, i1, exceptions());
+ i1 = it - buf.begin();
+ if( ! parse_ok ) // the directive will be printed verbatim
+ continue;
+ i0=i1;
+ items_[cur_item].compute_states(); // process complex options, like zeropad, into params
+
+ int argN=items_[cur_item].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_item;
+ } // loop on %'s
+ BOOST_ASSERT(cur_item == num_items);