🔨 refactored code to avoid using strcpy/strlen/strcat (#463)
This commit is contained in:
parent
716485a965
commit
83a9c60dbd
2 changed files with 74 additions and 22 deletions
48
src/json.hpp
48
src/json.hpp
|
@ -38,7 +38,7 @@ SOFTWARE.
|
||||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
|
#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
|
||||||
#include <cstring> // strcpy, strlen
|
#include <cstring> // strlen
|
||||||
#include <forward_list> // forward_list
|
#include <forward_list> // forward_list
|
||||||
#include <functional> // function, hash, less
|
#include <functional> // function, hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
|
@ -8259,6 +8259,7 @@ class basic_json
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
// special case for "0"
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
m_buf[0] = '0';
|
m_buf[0] = '0';
|
||||||
|
@ -8291,9 +8292,17 @@ class basic_json
|
||||||
template<typename NumberType>
|
template<typename NumberType>
|
||||||
void x_write(NumberType x, /*is_integral=*/std::false_type)
|
void x_write(NumberType x, /*is_integral=*/std::false_type)
|
||||||
{
|
{
|
||||||
|
// special case for 0.0 and -0.0
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0");
|
size_t i = 0;
|
||||||
|
if (std::signbit(x))
|
||||||
|
{
|
||||||
|
m_buf[i++] = '-';
|
||||||
|
}
|
||||||
|
m_buf[i++] = '0';
|
||||||
|
m_buf[i++] = '.';
|
||||||
|
m_buf[i] = '0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8342,18 +8351,35 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine if need to append ".0"
|
// determine if need to append ".0"
|
||||||
const auto data_end = m_buf.begin() + strlen(m_buf.data());
|
size_t i = 0;
|
||||||
|
bool value_is_int_like = true;
|
||||||
const bool value_is_int_like =
|
for (i = 0; i < m_buf.size(); ++i)
|
||||||
std::none_of(m_buf.begin(), data_end, [](const char c)
|
|
||||||
{
|
{
|
||||||
return (c == '.' or c == 'e' or c == 'E');
|
// break when end of number is reached
|
||||||
});
|
if (m_buf[i] == '\0')
|
||||||
assert(data_end + 2 < m_buf.end());
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we find non-int character
|
||||||
|
value_is_int_like = value_is_int_like and m_buf[i] != '.' and
|
||||||
|
m_buf[i] != 'e' and m_buf[i] != 'E';
|
||||||
|
}
|
||||||
|
|
||||||
if (value_is_int_like)
|
if (value_is_int_like)
|
||||||
{
|
{
|
||||||
strcat(m_buf.data(), ".0");
|
// there must be 2 bytes left for ".0"
|
||||||
|
assert((i + 2) < m_buf.size());
|
||||||
|
// we write to the end of the number
|
||||||
|
assert(m_buf[i] == '\0');
|
||||||
|
assert(m_buf[i - 1] != '\0');
|
||||||
|
|
||||||
|
// add ".0"
|
||||||
|
m_buf[i] = '.';
|
||||||
|
m_buf[i + 1] = '0';
|
||||||
|
|
||||||
|
// the resulting string is properly terminated
|
||||||
|
assert(m_buf[i + 2] == '\0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11136,7 +11162,7 @@ basic_json_parser_74:
|
||||||
// update data to point to the modified bytes
|
// update data to point to the modified bytes
|
||||||
if ((len + 1) < buf.size())
|
if ((len + 1) < buf.size())
|
||||||
{
|
{
|
||||||
std::copy(m_start, m_end, buf.data());
|
std::copy(m_start, m_end, buf.begin());
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
buf[ds_pos] = decimal_point_char;
|
buf[ds_pos] = decimal_point_char;
|
||||||
data = buf.data();
|
data = buf.data();
|
||||||
|
|
|
@ -38,7 +38,7 @@ SOFTWARE.
|
||||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
|
#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
|
||||||
#include <cstring> // strcpy, strlen
|
#include <cstring> // strlen
|
||||||
#include <forward_list> // forward_list
|
#include <forward_list> // forward_list
|
||||||
#include <functional> // function, hash, less
|
#include <functional> // function, hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
|
@ -8259,6 +8259,7 @@ class basic_json
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
// special case for "0"
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
m_buf[0] = '0';
|
m_buf[0] = '0';
|
||||||
|
@ -8291,9 +8292,17 @@ class basic_json
|
||||||
template<typename NumberType>
|
template<typename NumberType>
|
||||||
void x_write(NumberType x, /*is_integral=*/std::false_type)
|
void x_write(NumberType x, /*is_integral=*/std::false_type)
|
||||||
{
|
{
|
||||||
|
// special case for 0.0 and -0.0
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
std::strcpy(m_buf.data(), std::signbit(x) ? "-0.0" : "0.0");
|
size_t i = 0;
|
||||||
|
if (std::signbit(x))
|
||||||
|
{
|
||||||
|
m_buf[i++] = '-';
|
||||||
|
}
|
||||||
|
m_buf[i++] = '0';
|
||||||
|
m_buf[i++] = '.';
|
||||||
|
m_buf[i] = '0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8342,18 +8351,35 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine if need to append ".0"
|
// determine if need to append ".0"
|
||||||
const auto data_end = m_buf.begin() + strlen(m_buf.data());
|
size_t i = 0;
|
||||||
|
bool value_is_int_like = true;
|
||||||
const bool value_is_int_like =
|
for (i = 0; i < m_buf.size(); ++i)
|
||||||
std::none_of(m_buf.begin(), data_end, [](const char c)
|
|
||||||
{
|
{
|
||||||
return (c == '.' or c == 'e' or c == 'E');
|
// break when end of number is reached
|
||||||
});
|
if (m_buf[i] == '\0')
|
||||||
assert(data_end + 2 < m_buf.end());
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we find non-int character
|
||||||
|
value_is_int_like = value_is_int_like and m_buf[i] != '.' and
|
||||||
|
m_buf[i] != 'e' and m_buf[i] != 'E';
|
||||||
|
}
|
||||||
|
|
||||||
if (value_is_int_like)
|
if (value_is_int_like)
|
||||||
{
|
{
|
||||||
strcat(m_buf.data(), ".0");
|
// there must be 2 bytes left for ".0"
|
||||||
|
assert((i + 2) < m_buf.size());
|
||||||
|
// we write to the end of the number
|
||||||
|
assert(m_buf[i] == '\0');
|
||||||
|
assert(m_buf[i - 1] != '\0');
|
||||||
|
|
||||||
|
// add ".0"
|
||||||
|
m_buf[i] = '.';
|
||||||
|
m_buf[i + 1] = '0';
|
||||||
|
|
||||||
|
// the resulting string is properly terminated
|
||||||
|
assert(m_buf[i + 2] == '\0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -10170,7 +10196,7 @@ class basic_json
|
||||||
// update data to point to the modified bytes
|
// update data to point to the modified bytes
|
||||||
if ((len + 1) < buf.size())
|
if ((len + 1) < buf.size())
|
||||||
{
|
{
|
||||||
std::copy(m_start, m_end, buf.data());
|
std::copy(m_start, m_end, buf.begin());
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
buf[ds_pos] = decimal_point_char;
|
buf[ds_pos] = decimal_point_char;
|
||||||
data = buf.data();
|
data = buf.data();
|
||||||
|
|
Loading…
Reference in a new issue