diff mbox

[v2] libstdc++: Add hexfloat/defaultfloat io manipulators.

Message ID 20141008100747.GV4197@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 8, 2014, 10:07 a.m. UTC
On 07/10/14 21:10 +0200, Andreas Schwab wrote:
>That cannot work.  std::__convert_from_v always passes __prec before
>__v, but the format is "%a".

Ah yes. I'm testing this fix now.

Comments

Jonathan Wakely Oct. 8, 2014, 1:55 p.m. UTC | #1
On 08/10/14 11:07 +0100, Jonathan Wakely wrote:
>On 07/10/14 21:10 +0200, Andreas Schwab wrote:
>>That cannot work.  std::__convert_from_v always passes __prec before
>>__v, but the format is "%a".
>
>Ah yes. I'm testing this fix now.

Committed.

I assume it was working for me because __convert_from_v("%a", 6, 272.)
happens to pass the double differently from the integer, and vsnprintf
looks for a double in the relevant register and ignores the integer
argument.


>commit 543771e2db1642715854ae4bec81d803ca8e2e59
>Author: Jonathan Wakely <jwakely@redhat.com>
>Date:   Wed Oct 8 10:39:27 2014 +0100
>
>    	* include/bits/locale_facets.tcc (num_put::_M_insert_float): Do not
>    	pass precision when using hexfloat format.
>    	* src/c++98/locale_facets.cc (__num_base::_S_format_float): Always
>    	output precision if C99 hexfloat conversion specifiers not available.
>
>diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
>index cf12a08..88adc0d 100644
>--- a/libstdc++-v3/include/bits/locale_facets.tcc
>+++ b/libstdc++-v3/include/bits/locale_facets.tcc
>@@ -988,20 +988,32 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
> 	__num_base::_S_format_float(__io, __fbuf, __mod);
> 
> #ifdef _GLIBCXX_USE_C99
>+	// Precision is always used except for hexfloat format.
>+	const bool __use_prec =
>+	  (__io.flags() & ios_base::floatfield) != ios_base::floatfield;
>+
> 	// First try a buffer perhaps big enough (most probably sufficient
> 	// for non-ios_base::fixed outputs)
> 	int __cs_size = __max_digits * 3;
> 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
>-	__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>-				      __fbuf, __prec, __v);
>+	if (__use_prec)
>+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>+					__fbuf, __prec, __v);
>+	else
>+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>+					__fbuf, __v);
> 
> 	// If the buffer was not large enough, try again with the correct size.
> 	if (__len >= __cs_size)
> 	  {
> 	    __cs_size = __len + 1;
> 	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
>-	    __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>-					  __fbuf, __prec, __v);
>+	    if (__use_prec)
>+	      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>+					    __fbuf, __prec, __v);
>+	    else
>+	      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
>+					    __fbuf, __v);
> 	  }
> #else
> 	// Consider the possibility of long ios_base::fixed outputs
>diff --git a/libstdc++-v3/src/c++98/locale_facets.cc b/libstdc++-v3/src/c++98/locale_facets.cc
>index 7ed04e6..b3ca5dc 100644
>--- a/libstdc++-v3/src/c++98/locale_facets.cc
>+++ b/libstdc++-v3/src/c++98/locale_facets.cc
>@@ -71,7 +71,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 
>     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
> 
>+#ifdef _GLIBCXX_USE_C99
>+    // Precision is always used except for hexfloat format.
>     if (__fltfield != (ios_base::fixed | ios_base::scientific))
>+#endif
>       {
>         // As per DR 231: not only when __flags & ios_base::fixed || __prec > 0
>         *__fptr++ = '.';
diff mbox

Patch

commit 543771e2db1642715854ae4bec81d803ca8e2e59
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 8 10:39:27 2014 +0100

    	* include/bits/locale_facets.tcc (num_put::_M_insert_float): Do not
    	pass precision when using hexfloat format.
    	* src/c++98/locale_facets.cc (__num_base::_S_format_float): Always
    	output precision if C99 hexfloat conversion specifiers not available.

diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index cf12a08..88adc0d 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -988,20 +988,32 @@  _GLIBCXX_BEGIN_NAMESPACE_LDBL
 	__num_base::_S_format_float(__io, __fbuf, __mod);
 
 #ifdef _GLIBCXX_USE_C99
+	// Precision is always used except for hexfloat format.
+	const bool __use_prec =
+	  (__io.flags() & ios_base::floatfield) != ios_base::floatfield;
+
 	// First try a buffer perhaps big enough (most probably sufficient
 	// for non-ios_base::fixed outputs)
 	int __cs_size = __max_digits * 3;
 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-	__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-				      __fbuf, __prec, __v);
+	if (__use_prec)
+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					__fbuf, __prec, __v);
+	else
+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					__fbuf, __v);
 
 	// If the buffer was not large enough, try again with the correct size.
 	if (__len >= __cs_size)
 	  {
 	    __cs_size = __len + 1;
 	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-	    __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-					  __fbuf, __prec, __v);
+	    if (__use_prec)
+	      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					    __fbuf, __prec, __v);
+	    else
+	      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					    __fbuf, __v);
 	  }
 #else
 	// Consider the possibility of long ios_base::fixed outputs
diff --git a/libstdc++-v3/src/c++98/locale_facets.cc b/libstdc++-v3/src/c++98/locale_facets.cc
index 7ed04e6..b3ca5dc 100644
--- a/libstdc++-v3/src/c++98/locale_facets.cc
+++ b/libstdc++-v3/src/c++98/locale_facets.cc
@@ -71,7 +71,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
 
+#ifdef _GLIBCXX_USE_C99
+    // Precision is always used except for hexfloat format.
     if (__fltfield != (ios_base::fixed | ios_base::scientific))
+#endif
       {
         // As per DR 231: not only when __flags & ios_base::fixed || __prec > 0
         *__fptr++ = '.';