formatting refactor

This commit is contained in:
Billy Donahue 2018-05-11 10:20:04 -04:00
parent cf73619e28
commit 4cec95a2e7
2 changed files with 60 additions and 55 deletions

View File

@ -88,41 +88,49 @@ static inline void uintToString(LargestUInt value, char*& current) {
* We had a sophisticated way, but it did not work in WinCE. * We had a sophisticated way, but it did not work in WinCE.
* @see https://github.com/open-source-parsers/jsoncpp/pull/9 * @see https://github.com/open-source-parsers/jsoncpp/pull/9
*/ */
static inline void fixNumericLocale(char* begin, char* end) { template <typename Iter>
while (begin < end) { Iter fixNumericLocale(Iter begin, Iter end) {
for (; begin != end; ++begin) {
if (*begin == ',') { if (*begin == ',') {
*begin = '.'; *begin = '.';
} }
++begin;
} }
return begin;
} }
static inline void fixNumericLocaleInput(char* begin, char* end) { template <typename Iter>
void fixNumericLocaleInput(Iter begin, Iter end) {
char decimalPoint = getDecimalPoint(); char decimalPoint = getDecimalPoint();
if (decimalPoint != '\0' && decimalPoint != '.') { if (decimalPoint == '\0' || decimalPoint == '.') {
while (begin < end) { return;
if (*begin == '.') { }
*begin = decimalPoint; for (; begin != end; ++begin) {
} if (*begin == '.') {
++begin; *begin = decimalPoint;
} }
} }
} }
/** /**
* Delete zeros in the end of string, if it isn't last zero before '.' character. * Return iterator that would be the new end of the range [begin,end), if we
* were to delete zeros in the end of string, but not the last zero before '.'.
*/ */
static inline void fixZerosInTheEnd(char* begin, char* end) { template <typename Iter>
end--; Iter fixZerosInTheEnd(Iter begin, Iter end) {
while ((begin < end) && (*end == '0')) {
// don't delete last zero before point. for (; begin != end; --end) {
if (*(end - 1) != '.') { if (*(end-1) != '0') {
*end = '\0'; return end;
}
// Don't delete the last zero before the decimal point.
if (begin != (end-1) && *(end-2) == '.') {
return end;
} }
end--;
} }
return end;
} }
} // namespace Json { } // namespace Json
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED

View File

@ -127,48 +127,45 @@ JSONCPP_STRING valueToString(UInt value) {
namespace { namespace {
JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision, PrecisionType precisionType) { JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision, PrecisionType precisionType) {
// Allocate a buffer that is more than large enough to store the 16 digits of
// precision requested below.
char buffer[36];
int len = -1;
char formatString[15];
if (precisionType == PrecisionType::significantDigits) {
snprintf(formatString, sizeof(formatString), "%%.%ug", precision);
} else {
snprintf(formatString, sizeof(formatString), "%%.%uf", precision);
}
// Print into the buffer. We need not request the alternative representation // Print into the buffer. We need not request the alternative representation
// that always has a decimal point because JSON doesn't distinguish the // that always has a decimal point because JSON doesn't distinguish the
// concepts of reals and integers. // concepts of reals and integers.
if (isfinite(value)) { if (!isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), formatString, value); static const char* const reps[2][3] = {
fixNumericLocale(buffer, buffer + len); {"NaN", "-Infinity", "Infinity"},
// to delete use-less too much zeros in the end of string {"null", "-1e+9999", "1e+9999"}};
if (precisionType == PrecisionType::decimalPlaces) { return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0 : (value < 0) ? 1 : 2];
fixZerosInTheEnd(buffer, buffer + len); }
}
JSONCPP_STRING buffer(36, '\0');
// try to ensure we preserve the fact that this was given to us as a double on input while (true) {
if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { int len = snprintf(&*buffer.begin(), buffer.size(),
strcat(buffer, ".0"); (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
} precision, value);
assert(len >= 0);
} else { size_t wouldPrint = static_cast<size_t>(len);
if (wouldPrint >= buffer.size()) {
if (isnan(value)) { buffer.resize(wouldPrint + 1);
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); continue;
} else if (value < 0) { }
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); buffer.resize(wouldPrint);
} else { break;
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); }
}
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
}
// try to ensure we preserve the fact that this was given to us as a double on input
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
buffer += ".0";
} }
assert(len >= 0);
return buffer; return buffer;
} }
} } // namespace
JSONCPP_STRING valueToString(double value, unsigned int precision, PrecisionType precisionType) { JSONCPP_STRING valueToString(double value, unsigned int precision, PrecisionType precisionType) {
return valueToString(value, false, precision, precisionType); return valueToString(value, false, precision, precisionType);