vangyzen updated this revision to Diff 79625.
vangyzen added a comment.
Herald added a subscriber: emaste.

Restore support for a sign character preceding a "nan"

I accidentally broke +nan and -nan.  Add unit test cases for these,
and update my change to support them.


https://reviews.llvm.org/D26920

Files:
  include/locale
  
test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp

Index: test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp
===================================================================
--- test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp
+++ test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp
@@ -136,6 +136,30 @@
         assert(v == INFINITY);
     }
     {
+        const char str[] = "+Inf";
+        hex(ios);
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.goodbit);
+        assert(v == INFINITY);
+    }
+    {
+        const char str[] = "+iNF";
+        hex(ios);
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.goodbit);
+        assert(v == INFINITY);
+    }
+    {
         const char str[] = "-inf";
         hex(ios);
         std::ios_base::iostate err = ios.goodbit;
@@ -184,6 +208,30 @@
         assert(std::isnan(v));
     }
     {
+        const char str[] = "+NaN";
+        hex(ios);
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.goodbit);
+        assert(std::isnan(v));
+    }
+    {
+        const char str[] = "-nAn";
+        hex(ios);
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.goodbit);
+        assert(std::isnan(v));
+    }
+    {
         v = -1;
         const char str[] = "123_456_78_9;125";
         std::ios_base::iostate err = ios.goodbit;
@@ -208,6 +256,19 @@
         assert(v == 2);
     }
     {
+        // http://cplusplus.github.io/LWG/lwg-active.html#2381
+        v = -1;
+        const char str[] = "0x1a.bp+07p";
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(err == ios.goodbit);
+        assert(iter.base() == str+sizeof(str)-2);
+        assert(v == 0x1a.bp+07);
+    }
+    {
         v = -1;
         const char str[] = "1.79779e+309"; // unrepresentable
         std::ios_base::iostate err = ios.goodbit;
Index: include/locale
===================================================================
--- include/locale
+++ include/locale
@@ -505,17 +505,67 @@
         return -1;
     }
     if (__x == 'x' || __x == 'X')
-        __exp = 'P';
+    {
+        unsigned __sign = (*__a == '-') + (*__a == '+');
+        if (__a_end == __a + __sign + 1 && __a[__sign] == '0')
+            __exp = 'P';
+        else
+            return -1;
+    }
     else if ((__x & 0x5F) == __exp)
     {
+        if (__exp & 0x80)
+            return -1;
         __exp |= 0x80;
         if (__in_units)
         {
             __in_units = false;
             if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
                 *__g_end++ = __dc;
         }
     }
+    else if (__f > 9)
+    {
+        if (__x == 'P' || __x == 'p')
+            return -1;
+        unsigned __sign = (*__a == '-') + (*__a == '+');
+        if (__x == 'I' || __x == 'i')
+        {
+            if (__a_end != __a + __sign)    // start of Inf
+                return -1;
+        }
+        else if (__x == 'N' || __x == 'n')
+        {
+            bool __ok =
+                (__a_end == __a + __sign)               // start of NaN
+                ||
+                (__a_end == __a + __sign + 2 &&         // end of NaN
+                    (__a[__sign  ] & 0x5F) == 'N' &&
+                    (__a[__sign+1] & 0x5F) == 'A')
+                ||
+                (__a_end == __a + __sign + 1 &&         // middle of Inf
+                    (__a[__sign] & 0x5F) == 'I');
+            if (!__ok)
+                return -1;
+        }
+        else
+        {
+            // Only hex remains.
+            bool __ok =
+                __exp == 'P'                            // in a hex mantissa
+                ||
+                ((__x == 'A' || __x == 'a') &&          // middle of NaN
+                    __a_end == __a + __sign + 1 &&
+                        (__a[__sign] & 0x5F) == 'N')
+                ||
+                ((__x == 'F' || __x == 'f') &&          // end of Inf
+                    __a_end == __a + __sign + 2 &&
+                        (__a[__sign  ] & 0x5F) == 'I' &&
+                        (__a[__sign+1] & 0x5F) == 'N');
+            if (!__ok)
+                return -1;
+        }
+    }
     *__a_end++ = __x;
     if (__f >= 22)
         return 0;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to