ENH: MSVS 2013 snprintf compatible substitute

Simplify the backwards compatible snprintf configuration for pre
1900 version of MSVC.  Otherwise prefer C++11 syntax using std::snprintf.
This commit is contained in:
Hans Johnson 2018-12-12 13:31:55 -06:00 committed by Christopher Dunn
parent ccd077ffce
commit 5c8e539af4
5 changed files with 37 additions and 27 deletions

View File

@ -54,6 +54,14 @@
#define JSON_API #define JSON_API
#endif #endif
#if defined(_MSC_VER) && _MSC_VER < 1900
// As recommended at https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
extern JSON_API int msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format, ...);
# define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else
# define jsoncpp_snprintf std::snprintf
#endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
// integer // integer
// Storages, and 64 bits integer support is disabled. // Storages, and 64 bits integer support is disabled.

View File

@ -28,11 +28,7 @@ struct Options {
static JSONCPP_STRING normalizeFloatingPointStr(double value) { static JSONCPP_STRING normalizeFloatingPointStr(double value) {
char buffer[32]; char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) jsoncpp_snprintf(buffer, sizeof(buffer), "%.16g", value);
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#else
snprintf(buffer, sizeof(buffer), "%.16g", value);
#endif
buffer[sizeof(buffer) - 1] = 0; buffer[sizeof(buffer) - 1] = 0;
JSONCPP_STRING s(buffer); JSONCPP_STRING s(buffer);
JSONCPP_STRING::size_type index = s.find_last_of("eE"); JSONCPP_STRING::size_type index = s.find_last_of("eE");
@ -105,11 +101,7 @@ static void printValueTree(FILE* fout,
Json::ArrayIndex size = value.size(); Json::ArrayIndex size = value.size();
for (Json::ArrayIndex index = 0; index < size; ++index) { for (Json::ArrayIndex index = 0; index < size; ++index) {
static char buffer[16]; static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) jsoncpp_snprintf(buffer, sizeof(buffer), "[%u]", index);
sprintf_s(buffer, sizeof(buffer), "[%u]", index);
#else
snprintf(buffer, sizeof(buffer), "[%u]", index);
#endif
printValueTree(fout, value[index], path + buffer); printValueTree(fout, value[index], path + buffer);
} }
} break; } break;

View File

@ -22,21 +22,14 @@
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#include <cstdio> #include <cstdio>
#if !defined(snprintf)
#define snprintf std::snprintf
#endif
#if !defined(sscanf) #if !defined(sscanf)
#define sscanf std::sscanf #define sscanf std::sscanf
#endif #endif
#else #else
#include <stdio.h> #include <cstdio>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#if !defined(snprintf)
#define snprintf _snprintf
#endif
#endif #endif
#endif #endif
@ -813,7 +806,7 @@ JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
int line, column; int line, column;
getLocationLineAndColumn(location, line, column); getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1]; char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer; return buffer;
} }
@ -1833,7 +1826,7 @@ JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
int line, column; int line, column;
getLocationLineAndColumn(location, line, column); getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1]; char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer; return buffer;
} }

View File

@ -19,6 +19,29 @@
#include <algorithm> // min() #include <algorithm> // min()
#include <cstddef> // size_t #include <cstddef> // size_t
// Provide implementation equivalent of std::snprintf for older _MSC compilers
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdarg.h>
static int msvc_pre1900_c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
int JSON_API msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
va_list ap;
va_start(ap, format);
const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
// Disable warning C4702 : unreachable code // Disable warning C4702 : unreachable code
#if defined(_MSC_VER) && _MSC_VER >= 1800 // VC++ 12.0 and above #if defined(_MSC_VER) && _MSC_VER >= 1800 // VC++ 12.0 and above
#pragma warning(disable : 4702) #pragma warning(disable : 4702)

View File

@ -27,9 +27,6 @@
#define isfinite std::isfinite #define isfinite std::isfinite
#endif #endif
#if !defined(snprintf)
#define snprintf std::snprintf
#endif
#else #else
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
@ -46,9 +43,6 @@
#endif #endif
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#if !defined(snprintf)
#define snprintf _snprintf
#endif
#endif #endif
#if defined(__sun) && defined(__SVR4) // Solaris #if defined(__sun) && defined(__SVR4) // Solaris
@ -145,7 +139,7 @@ JSONCPP_STRING valueToString(double value,
JSONCPP_STRING buffer(size_t(36), '\0'); JSONCPP_STRING buffer(size_t(36), '\0');
while (true) { while (true) {
int len = snprintf( int len = jsoncpp_snprintf(
&*buffer.begin(), buffer.size(), &*buffer.begin(), buffer.size(),
(precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
precision, value); precision, value);