1048 // keep track of written items |
1048 // keep track of written items |
1049 // the idea is to reduce the number of jumps for error checking |
1049 // the idea is to reduce the number of jumps for error checking |
1050 size_t actual = 0, expected = 0; |
1050 size_t actual = 0, expected = 0; |
1051 |
1051 |
1052 // small buffer for number to string conversions |
1052 // small buffer for number to string conversions |
1053 char numbuf[32]; |
1053 char numbuf[40]; |
1054 |
1054 |
1055 // recursively write the values |
1055 // recursively write the values |
1056 switch (value->type) { |
1056 switch (value->type) { |
1057 case CX_JSON_OBJECT: { |
1057 case CX_JSON_OBJECT: { |
1058 const char *begin_obj = "{\n"; |
1058 const char *begin_obj = "{\n"; |
1158 actual += wfunc("\"", 1, 1, target); |
1158 actual += wfunc("\"", 1, 1, target); |
1159 expected += 2 + value->value.string.length; |
1159 expected += 2 + value->value.string.length; |
1160 break; |
1160 break; |
1161 } |
1161 } |
1162 case CX_JSON_NUMBER: { |
1162 case CX_JSON_NUMBER: { |
1163 // TODO: locale bullshit |
1163 int precision = settings->frac_max_digits; |
1164 // TODO: formatting settings |
1164 // because of the way how %g is defined, we need to |
1165 snprintf(numbuf, 32, "%g", value->value.number); |
1165 // double the precision and truncate ourselves |
1166 size_t len = strlen(numbuf); |
1166 precision = 1 + (precision > 15 ? 30 : 2 * precision); |
1167 actual += wfunc(numbuf, 1, len, target); |
1167 snprintf(numbuf, 40, "%.*g", precision, value->value.number); |
1168 expected += len; |
1168 char *dot, *exp; |
|
1169 unsigned char max_digits; |
|
1170 // find the decimal separator and hope that it's one of . or , |
|
1171 dot = strchr(numbuf, '.'); |
|
1172 if (dot == NULL) { |
|
1173 dot = strchr(numbuf, ','); |
|
1174 } |
|
1175 if (dot == NULL) { |
|
1176 // no decimal separator found |
|
1177 // output everything until a possible exponent |
|
1178 max_digits = 30; |
|
1179 dot = numbuf; |
|
1180 } else { |
|
1181 // found a decimal separator |
|
1182 // output everything until the separator |
|
1183 // and set max digits to what the settings say |
|
1184 size_t len = dot - numbuf; |
|
1185 actual += wfunc(numbuf, 1, len, target); |
|
1186 expected += len; |
|
1187 max_digits = settings->frac_max_digits; |
|
1188 if (max_digits > 15) { |
|
1189 max_digits = 15; |
|
1190 } |
|
1191 // locale independent separator |
|
1192 if (max_digits > 0) { |
|
1193 actual += wfunc(".", 1, 1, target); |
|
1194 expected++; |
|
1195 } |
|
1196 dot++; |
|
1197 } |
|
1198 // find the exponent |
|
1199 exp = strchr(dot, 'e'); |
|
1200 if (exp == NULL) { |
|
1201 // no exponent - output the rest |
|
1202 if (max_digits > 0) { |
|
1203 size_t len = strlen(dot); |
|
1204 if (len > max_digits) { |
|
1205 len = max_digits; |
|
1206 } |
|
1207 actual += wfunc(dot, 1, len, target); |
|
1208 expected += len; |
|
1209 } |
|
1210 } else { |
|
1211 // exponent found - truncate the frac digits |
|
1212 // and then output the rest |
|
1213 if (max_digits > 0) { |
|
1214 size_t len = exp - dot - 1; |
|
1215 if (len > max_digits) { |
|
1216 len = max_digits; |
|
1217 } |
|
1218 actual += wfunc(dot, 1, len, target); |
|
1219 expected += len; |
|
1220 } |
|
1221 actual += wfunc("e", 1, 1, target); |
|
1222 expected++; |
|
1223 exp++; |
|
1224 size_t len = strlen(exp); |
|
1225 actual += wfunc(exp, 1, len, target); |
|
1226 expected += len; |
|
1227 } |
1169 break; |
1228 break; |
1170 } |
1229 } |
1171 case CX_JSON_INTEGER: { |
1230 case CX_JSON_INTEGER: { |
1172 snprintf(numbuf, 32, "%" PRIi64, value->value.integer); |
1231 snprintf(numbuf, 32, "%" PRIi64, value->value.integer); |
1173 size_t len = strlen(numbuf); |
1232 size_t len = strlen(numbuf); |