]> git.lyx.org Git - lyx.git/blobdiff - boost/boost/format/parsing.hpp
boost 1.30.2
[lyx.git] / boost / boost / format / parsing.hpp
index eeda155a648820f6bd7557ab09d9c3a50259ffa3..1e75392d9bcb8b6e83f22b64075111d1aef95dde 100644 (file)
@@ -9,7 +9,7 @@
 //  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
+// ideas taken from Rudiger Loos's format class
 // and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
 
 // ------------------------------------------------------------------------------
 #ifndef BOOST_FORMAT_PARSING_HPP
 #define BOOST_FORMAT_PARSING_HPP
 
-#ifdef BOOST_MSVC
-#ifdef isdigit
-#undef isdigit
-#endif
-#endif // MSVC workaround
 
-#include <locale>
+#include <boost/format/format_class.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/assert.hpp>
 
 
-
-#include "boost/format/format_class.hpp"
-#include "boost/throw_exception.hpp"
-
 namespace boost {
 namespace io {
 namespace detail {
 
+  template<class Ch, class Stream> inline
+  bool wrap_isdigit(Ch 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, class Ch, class Tr> inline
-  Res str2int(const std::basic_string<Ch, Tr>& s,
-             typename std::basic_string<Ch, Tr>::size_type start,
-             BOOST_IO_STD basic_ios<Ch,Tr> &os,
-             const Res = Res(0)  )
+  Res str2int(const std::basic_string<Ch, Tr>& s, 
+              typename std::basic_string<Ch, Tr>::size_type start, 
+              BOOST_IO_STD basic_ios<Ch,Tr> &os,
+              const Res = Res(0)  ) 
     // Input : char string, with starting index
-    //         a stream, so we can use its locale  and call narrow.
+    //         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() && std::isdigit(s[start], os.rdbuf()->getloc() ) ) {
+    while(start<s.size() && wrap_isdigit(s[start], os) ) {
       char cur_ch = os.narrow( s[start], 0);
-      assert(cur_ch != 0 ); // since we called isdigit, this should not happen.
+      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
+      n += cur_ch - '0'; // 22.2.1.1.2 of the C++ standard
       ++start;
     }
     return n;
   }
 
   template<class Ch, class Tr>
-  void skip_asterisk(const std::basic_string<Ch,Tr> & buf,
-                    typename std::basic_string<Ch,Tr>::size_type * pos_p,
-                    BOOST_IO_STD basic_ios<Ch, Tr> &os)
+  void skip_asterisk(const std::basic_string<Ch,Tr> & buf, 
+                     typename std::basic_string<Ch,Tr>::size_type * pos_p,
+                     BOOST_IO_STD basic_ios<Ch, Tr> &os)
     // skip printf's "asterisk-fields" directives in the format-string buf
     // Input : char string, with starting index *pos_p
-    //         a stream, so we can use its locale  and call narrow.
+    //         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
   {
-    assert( pos_p != 0);
+    using namespace std;
+    BOOST_ASSERT( pos_p != 0);
     if(*pos_p >= buf.size() ) return;
     if(buf[ *pos_p]==os.widen('*')) {
       ++ (*pos_p);
-      while (*pos_p < buf.size() && std::isdigit(buf[*pos_p],os.rdbuf()->getloc())) ++(*pos_p);
+      while (*pos_p < buf.size() && wrap_isdigit(buf[*pos_p],os)) ++(*pos_p);
       if(buf[*pos_p]==os.widen('$')) ++(*pos_p);
     }
   }
@@ -85,253 +90,253 @@ namespace detail {
     // 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());
+          boost::throw_exception(io::bad_format_string());
   }
-
+    
 
 
   template<class Ch, class Tr>
   bool parse_printf_directive(const std::basic_string<Ch, Tr> & buf,
-                             typename std::basic_string<Ch, Tr>::size_type * pos_p,
-                             detail::format_item<Ch, Tr> * fpar,
-                             BOOST_IO_STD basic_ios<Ch,Tr> &os,
-                             unsigned char exceptions)
+                              typename std::basic_string<Ch, Tr>::size_type * pos_p,
+                              detail::format_item<Ch, Tr> * fpar,
+                              BOOST_IO_STD basic_ios<Ch,Tr> &os,
+                              unsigned char exceptions)
     // Input   : a 'printf-directive' in the format-string, starting at buf[ *pos_p ]
-    //           a stream merely to call 'widen' member function in the desired locale.
+    //           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 succeded (possibly ignoring errors if exceptions disabled)
+    // 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<Ch, Tr>  format_item_t;
-    assert( pos_p != 0);
-    typename std::basic_string<Ch, Tr>::size_type       &i1 = *pos_p,
-                                                       i0;
+    BOOST_ASSERT( pos_p != 0);
+    typename std::basic_string<Ch, Tr>::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]==os.widen('|'))
       {
-       in_brackets=true;
-       if( ++i1 >= buf.size() ) {
-         maybe_throw_exception(exceptions);
-         return false;
-       }
+        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]==os.widen('0'))
+    if(buf[i1]==os.widen('0')) 
       goto parse_flags;
 
     // handle argument order (%2$d)  or possibly width specification: %2d
     i0 = i1;  // save position before digits
-    while (i1 < buf.size() && std::isdigit(buf[i1], os.rdbuf()->getloc()))
+    while (i1 < buf.size() && wrap_isdigit(buf[i1], os))
       ++i1;
-    if (i1!=i0)
+    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] == os.widen('%') )
-         {
-           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]==os.widen('$') )
-         {
-           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;
-         }
+        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] == os.widen('%') ) 
+          {
+            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]==os.widen('$') ) 
+          {
+            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:
+    
+  parse_flags: 
     // handle flags
     while ( i1 <buf.size()) // as long as char is one of + - = # 0 l h   or ' '
-      {
-       // misc switches
-       switch (os.narrow(buf[i1], 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->ref_state_.flags_ |= std::ios_base::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_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->ref_state_.flags_ |= std::ios_base::showpoint | std::ios_base::showbase;
-           break;
-         default:
-           goto parse_width;
-         }
-       ++i1;
+      {  
+        // misc switches
+        switch (os.narrow(buf[i1], 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->ref_state_.flags_ |= std::ios_base::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_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->ref_state_.flags_ |= std::ios_base::showpoint | std::ios_base::showbase;
+            break;
+          default:
+            goto parse_width;
+          }
+        ++i1;
       } // loop on flag.
     if( i1>=buf.size()) {
       maybe_throw_exception(exceptions);
-      return true;
+      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() && std::isdigit(buf[i1], os.rdbuf()->getloc()))
+    while (i1<buf.size() && wrap_isdigit(buf[i1], os))
       i1++;
-
-    if (i1!=i0)
+    
+    if (i1!=i0) 
       { fpar->ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); }
 
   parse_precision:
-    if( i1>=buf.size()) {
+    if( i1>=buf.size()) { 
       maybe_throw_exception(exceptions);
       return true;
     }
     // handle precision spec
-    if (buf[i1]==os.widen('.'))
+    if (buf[i1]==os.widen('.'))  
       {
-       ++i1;
-       skip_asterisk(buf, &i1, os);
-       i0 = i1;  // save position before digits
-       while (i1<buf.size() && std::isdigit(buf[i1], os.rdbuf()->getloc()))
-         ++i1;
-
-       if(i1==i0)
-         fpar->ref_state_.precision_ = 0;
-       else
-         fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) );
+        ++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]==os.widen('l') || buf[i1]==os.widen('L') || buf[i1]==os.widen('h')) )
+    while( i1<buf.size() && 
+           ( buf[i1]==os.widen('l') || buf[i1]==os.widen('L') || buf[i1]==os.widen('h')) )
       ++i1;
     if( i1>=buf.size()) {
       maybe_throw_exception(exceptions);
       return true;
     }
-
-    if( in_brackets && buf[i1]==os.widen('|') )
+    
+    if( in_brackets && buf[i1]==os.widen('|') ) 
       {
-       ++i1;
-       return true;
+        ++i1;
+        return true;
       }
-    switch (os.narrow(buf[i1], 0) )
+    switch (os.narrow(buf[i1], 0) )  
       {
       case 'X':
-       fpar->ref_state_.flags_ |= std::ios_base::uppercase;
+        fpar->ref_state_.flags_ |= std::ios_base::uppercase;
       case 'p': // pointer => set hex.
       case 'x':
-       fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
-       fpar->ref_state_.flags_ |= std::ios_base::hex;
-       break;
-
+        fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
+        fpar->ref_state_.flags_ |= std::ios_base::hex;
+        break;
+      
       case 'o':
-       fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
-       fpar->ref_state_.flags_ |=  std::ios_base::oct;
-       break;
+        fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
+        fpar->ref_state_.flags_ |=  std::ios_base::oct;
+        break;
 
       case 'E':
-       fpar->ref_state_.flags_ |=  std::ios_base::uppercase;
+        fpar->ref_state_.flags_ |=  std::ios_base::uppercase;
       case 'e':
-       fpar->ref_state_.flags_ &= ~std::ios_base::floatfield;
-       fpar->ref_state_.flags_ |=  std::ios_base::scientific;
-
-       fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
-       fpar->ref_state_.flags_ |=  std::ios_base::dec;
-       break;
+        fpar->ref_state_.flags_ &= ~std::ios_base::floatfield;
+        fpar->ref_state_.flags_ |=  std::ios_base::scientific;
 
+        fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
+        fpar->ref_state_.flags_ |=  std::ios_base::dec;
+        break;
+      
       case 'f':
-       fpar->ref_state_.flags_ &= ~std::ios_base::floatfield;
-       fpar->ref_state_.flags_ |=  std::ios_base::fixed;
+        fpar->ref_state_.flags_ &= ~std::ios_base::floatfield;
+        fpar->ref_state_.flags_ |=  std::ios_base::fixed;
       case 'u':
       case 'd':
       case 'i':
-       fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
-       fpar->ref_state_.flags_ |=  std::ios_base::dec;
-       break;
+        fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
+        fpar->ref_state_.flags_ |=  std::ios_base::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_ = os.widen(' ');
-       fpar->pad_scheme_ |= format_item_t::tabulation;
-       fpar->argN_ = format_item_t::argN_tabulation;
-       break;
+        ++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_ = os.widen(' ');
+        fpar->pad_scheme_ |= format_item_t::tabulation;
+        fpar->argN_ = format_item_t::argN_tabulation; 
+        break;
 
       case 'G':
-       fpar->ref_state_.flags_ |= std::ios_base::uppercase;
-       break;
+        fpar->ref_state_.flags_ |= std::ios_base::uppercase;
+        break;
       case 'g': // 'g' conversion is default for floats.
-       fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
-       fpar->ref_state_.flags_ |=  std::ios_base::dec;
+        fpar->ref_state_.flags_ &= ~std::ios_base::basefield;
+        fpar->ref_state_.flags_ |=  std::ios_base::dec;
 
-       // CLEAR all floatield flags, so stream will CHOOSE
-       fpar->ref_state_.flags_ &= ~std::ios_base::floatfield;
-       break;
+        // CLEAR all floatield flags, so stream will CHOOSE
+        fpar->ref_state_.flags_ &= ~std::ios_base::floatfield; 
+        break;
 
       case 'C':
-      case 'c':
-       fpar->truncate_ = 1;
-       break;
+      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);
+      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]==os.widen('|') )
-         {
-           ++i1;
-           return true;
-         }
-       else  maybe_throw_exception(exceptions);
+        if( i1<buf.size() && buf[i1]==os.widen('|') ) 
+          {
+            ++i1;
+            return true;
+          }
+        else  maybe_throw_exception(exceptions);
       }
     return true;
   }
@@ -344,98 +349,99 @@ namespace detail {
 //  format :: parse(..)
 
 template<class Ch, class Traits>
-void basic_format<Ch, Traits> ::parse(const string_t & buf)
+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;
+    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::npos )
+    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(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() && std::isdigit(buf[i1],oss_.rdbuf()->getloc())) ++i1;
+      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::npos )
+    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;
+        piece += buf.substr(i0, i1-i0) + buf[i1]; 
+        i1+=2; i0=i1;
+        continue; 
       }
-      assert(  static_cast<unsigned int>(cur_it) < items_.size() || cur_it==0);
+      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();
+      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;
+        continue;
       if(argN ==format_item_t::argN_no_posit)
-       ordered_args=false;
+        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
-    assert(cur_it == num_items);
-
+    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( !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
-       }
+        {
+          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;
-         }
+        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);