http://bugzilla.lyx.org/show_bug.cgi?id=4076

I have finally implemented all the missing facets for idocstreams.
Will commit the patch tomorrow if I don't get objections.
Jürgen, may I also commit to branch?

-- 
Enrico
Index: src/support/docstring.cpp
===================================================================
--- src/support/docstring.cpp   (revision 19230)
+++ src/support/docstring.cpp   (working copy)
@@ -560,20 +560,136 @@ public:
                string_num_get_facet() : std::num_get<char, 
std::basic_string<char>::iterator>(1) {}
        };
 
-private:
-       bool isNumpunct(lyx::char_type const c) const
+       /// Numpunct facet defining the I/O format.
+       class numpunct_facet : public std::numpunct<char>
        {
-               /// Only account for the standard numpunct "C" locale facet.
-               return c < 0x80 && (c == '-' || c == '+' || isdigit(c)
-                       || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
-                       || c == 'x' || c == 'X');
-       }
+       public:
+               numpunct_facet() : std::numpunct<char>(1) {}
+       };
 
 protected:
        iter_type
        do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, bool & v) const
+       {
+               // This facet has been adapted from the STLPort library
+               if (b.flags() & std::ios_base::boolalpha) {
+                       numpunct_facet p;
+                       lyx::docstring const truename = 
from_local8bit(p.truename());
+                       lyx::docstring const falsename = 
from_local8bit(p.falsename());
+                       bool true_ok = true;
+                       bool false_ok = true;
+                       size_t n = 0;
+                       for (; iit != eit; ++iit) {
+                               lyx::char_type c = *iit;
+                               true_ok  = true_ok  && (c == truename[n]);
+                               false_ok = false_ok && (c == falsename[n]);
+                               ++n;
+                               if ((!true_ok && !false_ok) ||
+                                   (true_ok  && n >= truename.size()) ||
+                                   (false_ok && n >= falsename.size())) {
+                                       ++iit;
+                                       break;
+                               }
+                       }
+                       if (true_ok  && n < truename.size())
+                               true_ok  = false;
+                       if (false_ok && n < falsename.size())
+                               false_ok = false;
+                       if (true_ok || false_ok) {
+                               err = std::ios_base::goodbit;
+                               v = true_ok;
+                       } else
+                               err = std::ios_base::failbit;
+                       if (iit == eit)
+                               err |= std::ios_base::eofbit;
+                       return iit;
+               } else {
+                       long l;
+                       iter_type end = this->do_get(iit, eit, b, err, l);
+                       if (!(err & std::ios_base::failbit)) {
+                               if (l == 0)
+                                       v = false;
+                               else if (l == 1)
+                                       v = true;
+                               else
+                                       err |= std::ios_base::failbit;
+                       }
+                       return end;
+               }
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
                std::ios_base::iostate & err, long & v) const
        {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, unsigned short & v) const
+       {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, unsigned int & v) const
+       {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, unsigned long & v) const
+       {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, long long & v) const
+       {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, unsigned long long & v) const
+       {
+               return do_get_integral(iit, eit, b, err, v);
+       }
+#endif
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, float & v) const
+       {
+               return do_get_float(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, double & v) const
+       {
+               return do_get_float(iit, eit, b, err, v);
+       }
+
+       iter_type
+       do_get(iter_type iit, iter_type eit, std::ios_base & b,
+               std::ios_base::iostate & err, long double & v) const
+       {
+               return do_get_float(iit, eit, b, err, v);
+       }
+
+private:
+       template <typename ValueType>
+       iter_type
+       do_get_integral(iter_type iit, iter_type eit, std::ios_base & b,
+                       std::ios_base::iostate & err, ValueType & v) const
+       {
                std::string s;
                s.reserve(64);
                for (; iit != eit && isNumpunct(*iit); ++iit)
@@ -588,6 +704,58 @@ protected:
 
                return iit;
        }
+
+       bool isNumpunct(lyx::char_type const c) const
+       {
+               /// Only account for the standard numpunct "C" locale facet.
+               return c < 0x80 && (c == '-' || c == '+' || isdigit(c)
+                       || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
+                       || c == 'x' || c == 'X');
+       }
+
+       template <typename ValueType>
+       iter_type
+       do_get_float(iter_type iit, iter_type eit, std::ios_base & b,
+                       std::ios_base::iostate & err, ValueType & v) const
+       {
+               // Gather a string of the form
+               // [+-]? [0-9]* .? [0-9]* ([eE] [+-]? [0-9]+)?
+               std::string s;
+               s.reserve(64);
+               char c;
+               numpunct_facet p;
+               char const dot = p.decimal_point();
+               char const sep = p.thousands_sep();
+               // Get an optional sign
+               if (iit != eit && (*iit == '-' || *iit == '+')) {
+                       s += static_cast<char>(*iit);
+                       ++iit;
+               }
+               for (; iit != eit && isDigitOrSep(*iit, sep); ++iit)
+                       s += static_cast<char>(*iit);
+               if (iit != eit && *iit == dot) {
+                       s += dot;
+                       ++iit;
+                       for (; iit != eit && isDigitOrSep(*iit, 0); ++iit)
+                               s += static_cast<char>(*iit);
+                       if (iit != eit && (*iit == 'e' || *iit == 'E')) {
+                               s += static_cast<char>(*iit);
+                               ++iit;
+                               for (; iit != eit && isDigitOrSep(*iit, 0); 
++iit)
+                                       s += static_cast<char>(*iit);
+                       }
+               }
+               s += '\n';
+               string_num_get_facet f;
+               f.get(s.begin(), s.end(), b, err, v);
+
+               return iit;
+       }
+
+       bool isDigitOrSep(lyx::char_type const c, char const sep) const
+       {
+               return (c >= '0' && c <= '9') || (c != 0 && c == sep);
+       }
 };
 
 

Reply via email to