#include "json_numbers.h" #include "ryu/ryu.h" #include #include #include _Static_assert(sizeof(double)==8 && DBL_MANT_DIG==53 && DBL_MAX_EXP==1024, "Native JSON numbers require IEEE-754 binary64"); int native_json_format_double(char output[NATIVE_JSON_DOUBLE_CAPACITY], double value) { uint64_t bits; memcpy(&bits,&value,sizeof(bits)); uint64_t magnitude=bits & UINT64_C(0x7fffffffffffffff); if (magnitude>=UINT64_C(0x7ff0000000000000)) return 0; if (magnitude==0) { if (bits>>63) { memcpy(output,"-0.0",4); return 4; } output[0]='0'; return 1; } int length=d2s_buffered_n(value,output); /* Ryu returns shortest significant digits in scientific notation. Use ordinary notation only when its JSON token is shorter. This moves an exact decimal point; it never recomputes or rounds the floating value. */ char digits[17]; int negative=output[0]=='-', count=0, pos=negative; while (output[pos]!='E') { if (output[pos]!='.') digits[count++]=output[pos]; pos++; } pos++; int exponent_negative=output[pos]=='-'; if (exponent_negative) pos++; int exponent=0; while (pos=count ? point : count+1); if (fixed_length>=length) return length; pos=0; if (negative) output[pos++]='-'; if (point<=0) { output[pos++]='0'; output[pos++]='.'; for (int i=0;i<-point;i++) output[pos++]='0'; memcpy(output+pos,digits,(size_t)count); pos+=count; } else { for (int i=0;i0 && write_bytes(file,text,(size_t)length); } int native_json_write_array(FILE *file, const double *values, size_t count, size_t stride) { if (!file || ferror(file) || (count && !values)) return 0; if (count>1 && (!stride || stride>(size_t)PTRDIFF_MAX/sizeof(double)/(count-1))) return 0; char buffer[65536]; size_t used=1; buffer[0]='['; for (size_t i=0;isizeof(buffer)-NATIVE_JSON_DOUBLE_CAPACITY-2) { if (!write_bytes(file,buffer,used)) return 0; used=0; } if (i) buffer[used++]=','; int length=native_json_format_double(buffer+used,values[i*stride]); if (!length) return 0; used+=(size_t)length; } buffer[used++]=']'; return write_bytes(file,buffer,used); }