1 #ifndef NUMBERTOSTRING_H
2 #define NUMBERTOSTRING_H
6 #ifdef JSON_LESS_MEMORY
7 #include "JSONMemory.h"
9 #include "JSONSharedString.h"
14 template <
unsigned int GETLENSIZE>
16 char tmp[GETLENSIZE == 16];
40 static inline bool _floatsAreEqual(
const json_number & one,
const json_number & two) json_pure;
41 static inline bool _floatsAreEqual(
const json_number & one,
const json_number & two) json_nothrow {
42 return (one > two) ? (one - two) < JSON_FLOAT_THRESHHOLD : (one - two) > -JSON_FLOAT_THRESHHOLD;
45 #ifdef JSON_LESS_MEMORY
46 #define num_str_result s.ptr
49 class NumberToString {
52 static json_string _itoa(T val) json_nothrow {
53 #ifdef JSON_LESS_MEMORY
54 json_auto<json_char> s(getLenSize<
sizeof(T)>::GETLEN);
56 json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
58 num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT(
'\0');
59 json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
63 long value = (long)val;
74 *runner-- = (json_char)(value % 10) + JSON_TEXT(
'0');
80 *runner = JSON_TEXT(
'-');
81 return json_string(runner);
83 return json_string(runner + 1);
88 static json_string _uitoa(T val) json_nothrow {
89 #ifdef JSON_LESS_MEMORY
90 json_auto<json_char> s(getLenSize<
sizeof(T)>::GETLEN);
92 json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
94 num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT(
'\0');
95 json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
99 unsigned long value = (
unsigned long)val;
101 *runner-- = (json_char)(value % 10) + JSON_TEXT(
'0');
102 }
while(value /= 10);
105 return json_string(runner + 1);
109 #ifdef JSON_ISO_STRICT
111 #define FLOAT_STRING "%f"
112 #define LFLOAT_STRING L"%f"
114 #define EXTRA_LONG long
115 #define FLOAT_STRING "%Lf"
116 #define LFLOAT_STRING L"%Lf"
119 static json_string _ftoa(json_number value) json_nothrow {
122 if (json_unlikely(value >= 0.0 && _floatsAreEqual(value, (json_number)((
unsigned EXTRA_LONG
long)value)))){
123 return _uitoa<unsigned EXTRA_LONG long>((
unsigned EXTRA_LONG long)value);
128 if (json_unlikely(_floatsAreEqual(value, (json_number)((
long EXTRA_LONG)value)))){
129 return _itoa<long EXTRA_LONG>((
long EXTRA_LONG)value);
132 #ifdef JSON_LESS_MEMORY
133 json_auto<json_char> s(64);
135 json_char num_str_result[64];
138 std::swprintf(num_str_result, 63, LFLOAT_STRING, (EXTRA_LONG
double)value);
142 _snprintf_s(num_str_result, 63, 63, FLOAT_STRING, (EXTRA_LONG
double)value);
144 snprintf(num_str_result, 63, FLOAT_STRING, (EXTRA_LONG
double)value);
148 for(json_char * pos = &num_str_result[0]; *pos; ++pos){
149 if (json_unlikely(*pos ==
'.')){
150 for(json_char * runner = pos + 1; *runner; ++runner){
151 if (json_likely(*runner != JSON_TEXT(
'0'))){
155 *pos = JSON_TEXT(
'\0');
159 return json_string(num_str_result);
162 #if defined(JSON_SAFE) || defined(JSON_DEBUG)
163 static bool isNumeric(
const json_string & str) json_nothrow {
164 const json_char * p = str.c_str();
165 bool decimal =
false;
166 bool scientific =
false;
169 bool leadingzero =
false;
174 case JSON_TEXT(
'\0'):
187 case JSON_TEXT(
'\0'):
197 case JSON_TEXT(
'\0'):
237 case JSON_TEXT(
'\0'):
260 return (str.find_first_not_of(JSON_TEXT(
"0123456789ABCDEFabcdef"), 2) == json_string::npos);
268 return (str.find_first_not_of(JSON_TEXT(
"01234567"), 1) == json_string::npos);
270 case JSON_TEXT(
'\0'):
285 if (json_unlikely(decimal)){
289 if (json_unlikely(scientific)){
296 if (json_unlikely(scientific)){
302 case JSON_TEXT(
'\0'):
306 if (!isdigit(*(p + 1))){
311 if (*(p + 1) == JSON_TEXT(
'0')){
350 if (leadingzero && !decimal){
360 static json_number _atof (
const json_char * num){
361 json_number sign = (json_number)1.0;
364 if (*num==JSON_TEXT(
'-')){
371 #if defined(JSON_SAFE) || defined(JSON_DEBUG)
372 bool _leadingzeros = *num == JSON_TEXT(
'0');
373 bool _leadingdigits =
false;
375 if (*num == JSON_TEXT(
'0')){
379 else if (json_likely(*num < JSON_TEXT(
'1') || *num > JSON_TEXT(
'9'))){
380 return std::numeric_limits<json_number>::signaling_NaN();
384 JSON_ASSERT_SAFE(*num != JSON_TEXT(
'0'), JSON_TEXT(
"multiple leading zeros"),
return std::numeric_limits<json_number>::signaling_NaN(); );
387 json_number n = (json_number)0.0;
388 if (json_likely(*num >= JSON_TEXT(
'1') && *num <= JSON_TEXT(
'9'))){
389 #if defined(JSON_SAFE) || defined(JSON_DEBUG)
390 _leadingdigits =
true;
393 n = (n * 10.0) + (*num++ - JSON_TEXT(
'0'));
394 }
while (*num >= JSON_TEXT(
'0') && *num <= JSON_TEXT(
'9'));
397 (*num) == JSON_TEXT(
'.') ||
398 (*num) == JSON_TEXT(
'e') ||
399 (*num) == JSON_TEXT(
'E') ||
400 (*num) == JSON_TEXT(
'\0')
401 , JSON_TEXT(
"first digit not a number, e, period, or terminator"),
return std::numeric_limits<json_number>::signaling_NaN(); );
405 json_number scale = (json_number)0.0;
406 if (*num == JSON_TEXT(
'.')) {
407 JSON_ASSERT_SAFE(_leadingzeros || _leadingdigits, JSON_TEXT(
"period without leading anything"),
return std::numeric_limits<json_number>::signaling_NaN(); );
409 for(; *num >= JSON_TEXT(
'0') && *num <= JSON_TEXT(
'9');){
410 n = (n * 10.0) + (*num++ - JSON_TEXT(
'0'));
414 JSON_ASSERT_SAFE(!_leadingzeros || n == 0, JSON_TEXT(
"leading zero on an int"),
return std::numeric_limits<json_number>::signaling_NaN(); );
416 (*num) == JSON_TEXT(
'e') ||
417 (*num) == JSON_TEXT(
'E') ||
418 (*num) == JSON_TEXT(
'\0')
419 , JSON_TEXT(
"next char not an e or terminator"),
return std::numeric_limits<json_number>::signaling_NaN(); );
423 int subscale = 0, signsubscale = 1;
424 if (json_unlikely(*num == JSON_TEXT(
'e') || *num == JSON_TEXT(
'E'))){
433 JSON_ASSERT_SAFE(*num != JSON_TEXT(
'0'), JSON_TEXT(
"negative cant be followed by leading zero even after E"),
return std::numeric_limits<json_number>::signaling_NaN(); );
438 JSON_ASSERT_SAFE(*num != JSON_TEXT(
'\0'), JSON_TEXT(
"no exponent for scientific notation"),
return std::numeric_limits<json_number>::signaling_NaN(); );
439 while (*num >= JSON_TEXT(
'0') && *num <= JSON_TEXT(
'9')){
440 subscale=(subscale * 10) + (*num++ - JSON_TEXT(
'0'));
444 JSON_ASSERT_SAFE(*num == JSON_TEXT(
'\0'), JSON_TEXT(
"done with number, not at terminator"),
return std::numeric_limits<json_number>::signaling_NaN(); );
445 return sign * n * pow((json_number)10.0, scale + subscale * signsubscale);