forked from OSchip/llvm-project
[libcxx][NFC] Tidy up calculation of __nbuf in num_put::do_put, and add comments
In07ef8e6796
and3ed9f6ebde
, `__nbuf` started to diverge from the amount of space that was actually needed for the buffer. For 32-bit longs for example, we allocate a buffer that is one larger than needed. Moreover, it is no longer clear exactly where the extra +1 or +2 comes from - they're just numbers pulled from thin air. This PR cleans up how `__nbuf` is calculated, and adds comments to further clarify where each part comes from. Specifically, it corrects the underestimation of the max size buffer needed that the above two commits had to compensate for. The root cause looks to be the use of signed type parameters to numeric_limits<>::digits. Since digits only counts non-sign bits, the calculation was acting as though (for a signed 64-bit type) the longest value we would print was 2^63 in octal. However, printing in octal treats values as unsigned, so it is actually 2^64. Thus, using unsigned types and changing the final +2 to a +1 is probably a better option. Reviewed By: #libc, ldionne, Mordante Differential Revision: https://reviews.llvm.org/D103339
This commit is contained in:
parent
5ecfdb5123
commit
06e047227d
|
@ -1458,10 +1458,12 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
|||
char __fmt[6] = {'%', 0};
|
||||
const char* __len = "l";
|
||||
this->__format_int(__fmt+1, __len, true, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<long>::digits / 3)
|
||||
+ ((numeric_limits<long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 2;
|
||||
// Worst case is octal, with showbase enabled. Note that octal is always
|
||||
// printed as an unsigned value.
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits
|
||||
+ ((numeric_limits<unsigned long>::digits % 3) != 0) // round up
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0) // base prefix
|
||||
+ 1; // terminating null character
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
char* __ne = __nar + __nc;
|
||||
|
@ -1485,10 +1487,12 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
|||
char __fmt[8] = {'%', 0};
|
||||
const char* __len = "ll";
|
||||
this->__format_int(__fmt+1, __len, true, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
|
||||
+ ((numeric_limits<long long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 2;
|
||||
// Worst case is octal, with showbase enabled. Note that octal is always
|
||||
// printed as an unsigned value.
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits
|
||||
+ ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0) // base prefix
|
||||
+ 1; // terminating null character
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
char* __ne = __nar + __nc;
|
||||
|
@ -1512,10 +1516,11 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
|||
char __fmt[6] = {'%', 0};
|
||||
const char* __len = "l";
|
||||
this->__format_int(__fmt+1, __len, false, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
|
||||
+ ((numeric_limits<unsigned long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 1;
|
||||
// Worst case is octal, with showbase enabled.
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits
|
||||
+ ((numeric_limits<unsigned long>::digits % 3) != 0) // round up
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0) // base prefix
|
||||
+ 1; // terminating null character
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
char* __ne = __nar + __nc;
|
||||
|
@ -1539,10 +1544,11 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
|||
char __fmt[8] = {'%', 0};
|
||||
const char* __len = "ll";
|
||||
this->__format_int(__fmt+1, __len, false, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
|
||||
+ ((numeric_limits<unsigned long long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 1;
|
||||
// Worst case is octal, with showbase enabled.
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits
|
||||
+ ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0) // base prefix
|
||||
+ 1; // terminating null character
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
char* __ne = __nar + __nc;
|
||||
|
|
Loading…
Reference in New Issue