src/json.c

changeset 1117
54df904472b0
parent 1116
b381da3a9b19
equal deleted inserted replaced
1116:b381da3a9b19 1117:54df904472b0
986 } 986 }
987 987
988 static const CxJsonWriter cx_json_writer_default = { 988 static const CxJsonWriter cx_json_writer_default = {
989 false, 989 false,
990 true, 990 true,
991 255, 991 6,
992 false, 992 false,
993 4 993 4
994 }; 994 };
995 995
996 CxJsonWriter cxJsonWriterCompact(void) { 996 CxJsonWriter cxJsonWriterCompact(void) {
999 999
1000 CxJsonWriter cxJsonWriterPretty(bool use_spaces) { 1000 CxJsonWriter cxJsonWriterPretty(bool use_spaces) {
1001 return (CxJsonWriter) { 1001 return (CxJsonWriter) {
1002 true, 1002 true,
1003 true, 1003 true,
1004 255, 1004 6,
1005 use_spaces, 1005 use_spaces,
1006 4 1006 4
1007 }; 1007 };
1008 } 1008 }
1009 1009
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);

mercurial