🚧 overworked fix for #465

This commit is contained in:
Niels Lohmann 2017-02-21 19:11:34 +01:00
parent 7d14f167b8
commit 967f9144d4
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
3 changed files with 43 additions and 33 deletions

View file

@ -53,11 +53,11 @@ clean:
# create Doxygen documentation # create Doxygen documentation
doxygen: create_output create_links doxygen: create_output create_links
doxygen doxygen
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType JSONSerializer >@@g' html/*.html
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType&#160;&gt;@@g' html/*.html $(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType&#160;JSONSerializer&#160;&gt;@@g' html/*.html
upload: clean doxygen check_output upload: clean doxygen check_output
cd html ; ../scripts/git-update-ghpages nlohmann/json cd html ; ../scripts/git-update-ghpages nlohmann/json

View file

@ -8252,9 +8252,8 @@ class basic_json
} }
private: private:
static constexpr size_t s_capacity = 30; /// a (hopefully) large enough character buffer
/// added capacity for leading '-' and trailing '\0' std::array < char, 64 > m_buf{{}};
std::array < char, s_capacity + 2 > m_buf{{}};
template<typename NumberType> template<typename NumberType>
void x_write(NumberType x, /*is_integral=*/std::true_type) void x_write(NumberType x, /*is_integral=*/std::true_type)
@ -8266,23 +8265,24 @@ class basic_json
return; return;
} }
static_assert(std::numeric_limits<NumberType>::digits10 <= s_capacity, const bool is_negative = x < 0;
"unexpected NumberType");
const bool is_neg = x < 0;
size_t i = 0; size_t i = 0;
while (x != 0 and i < s_capacity) // spare 1 byte for '\0'
while (x != 0 and i < m_buf.size() - 1)
{ {
const auto digit = std::labs(static_cast<long>(x % 10)); const auto digit = std::labs(static_cast<long>(x % 10));
m_buf[i++] = static_cast<char>('0' + digit); m_buf[i++] = static_cast<char>('0' + digit);
x /= 10; x /= 10;
} }
assert(i < s_capacity); // make sure the number has been processed completely
assert(x == 0);
if (is_neg) if (is_negative)
{ {
// make sure there is capacity for the '-'
assert(i < m_buf.size() - 2);
m_buf[i++] = '-'; m_buf[i++] = '-';
} }
@ -8306,11 +8306,16 @@ class basic_json
return; return;
} }
// get number of digits for a text -> float -> text round-trip
static constexpr auto d = std::numeric_limits<NumberType>::digits10; static constexpr auto d = std::numeric_limits<NumberType>::digits10;
static_assert(d == 6 or d == 15 or d == 16 or d == 17,
"unexpected NumberType");
snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); // the actual conversion
const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x);
// negative value indicates an error
assert(written_bytes > 0);
// check if buffer was large enough
assert(written_bytes < m_buf.size());
// read information from locale // read information from locale
const auto loc = localeconv(); const auto loc = localeconv();
@ -8324,7 +8329,7 @@ class basic_json
// erase thousands separator // erase thousands separator
if (thousands_sep != '\0') if (thousands_sep != '\0')
{ {
const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
std::fill(end, m_buf.end(), '\0'); std::fill(end, m_buf.end(), '\0');
} }

View file

@ -8252,9 +8252,8 @@ class basic_json
} }
private: private:
static constexpr size_t s_capacity = 30; /// a (hopefully) large enough character buffer
/// added capacity for leading '-' and trailing '\0' std::array < char, 64 > m_buf{{}};
std::array < char, s_capacity + 2 > m_buf{{}};
template<typename NumberType> template<typename NumberType>
void x_write(NumberType x, /*is_integral=*/std::true_type) void x_write(NumberType x, /*is_integral=*/std::true_type)
@ -8266,23 +8265,24 @@ class basic_json
return; return;
} }
static_assert(std::numeric_limits<NumberType>::digits10 <= s_capacity, const bool is_negative = x < 0;
"unexpected NumberType");
const bool is_neg = x < 0;
size_t i = 0; size_t i = 0;
while (x != 0 and i < s_capacity) // spare 1 byte for '\0'
while (x != 0 and i < m_buf.size() - 1)
{ {
const auto digit = std::labs(static_cast<long>(x % 10)); const auto digit = std::labs(static_cast<long>(x % 10));
m_buf[i++] = static_cast<char>('0' + digit); m_buf[i++] = static_cast<char>('0' + digit);
x /= 10; x /= 10;
} }
assert(i < s_capacity); // make sure the number has been processed completely
assert(x == 0);
if (is_neg) if (is_negative)
{ {
// make sure there is capacity for the '-'
assert(i < m_buf.size() - 2);
m_buf[i++] = '-'; m_buf[i++] = '-';
} }
@ -8306,11 +8306,16 @@ class basic_json
return; return;
} }
// get number of digits for a text -> float -> text round-trip
static constexpr auto d = std::numeric_limits<NumberType>::digits10; static constexpr auto d = std::numeric_limits<NumberType>::digits10;
static_assert(d == 6 or d == 15 or d == 16 or d == 17,
"unexpected NumberType");
snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x); // the actual conversion
const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x);
// negative value indicates an error
assert(written_bytes > 0);
// check if buffer was large enough
assert(written_bytes < m_buf.size());
// read information from locale // read information from locale
const auto loc = localeconv(); const auto loc = localeconv();
@ -8324,7 +8329,7 @@ class basic_json
// erase thousands separator // erase thousands separator
if (thousands_sep != '\0') if (thousands_sep != '\0')
{ {
const auto end = std::remove(m_buf.begin(), m_buf.end(), thousands_sep); const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
std::fill(end, m_buf.end(), '\0'); std::fill(end, m_buf.end(), '\0');
} }