#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdint.h>

char *fmtp04f(char *buf, char *lim, double d) {
    // if there's no space at all don't bother
    if(buf==lim) return buf;
    // 10 characters in maximum 32 bit integer, one for the dot,
    // one for the terminating NUL in debug prints
    char b[12];
    // current position in the buffer
    char *bp = b;
    // scale and round
    int32_t i = lrint(d * 10000.);
    // write sign and fix i sign
    // (we do have at least one character available in buf)
    if(signbit(d)) {
        *buf++='-';
        i = -i;
    } else {
        *buf++='+';
    }
    // *always* write down the last 4 digits, even if they are zeroes
    // (they'll become the 4 digits after the decimal dot)
    for(; bp!=b+4; ) {
        *bp++ = '0' + i%10;
        i/=10;
    }
    *bp++='.';
    // write down the remaining digits, writing at least one
    do {
        *bp++ = '0' + i%10;
        i/=10;
    } while(i != 0);
    // bp is at the character after the last, step back
    --bp;
    // data is now into b *in reversed order*;
    // reverse-copy it into the user-provided buffer
    while(buf!=lim) {
        *buf++ = *bp;
        // check before decrementing, as a pointer to one-before-first
        // is not allowed in C
        if(bp == b) break;
        --bp;
    }
    if(buf!=lim) *buf=0;    // "regular" case: terminate *after*
    else         lim[-1]=0; // bad case: truncate
    return buf;
}

void doformat(char *buf, char *lim, double a, double b) {
    if(buf==lim) return; // cannot do anything
    *buf++='{';
    if(buf==lim) goto end;
    buf = fmtp04f(buf, lim, a);
    if(buf==lim) return; // already terminated by fmtp04f
    *buf++=',';
    if(buf==lim) goto end;
    buf = fmtp04f(buf, lim, b);
    if(buf==lim) return; // idem
    *buf++='}';
    if(buf==lim) goto end;
    *buf++=0;
end:
    lim[-1]=0;   // always terminate
}

int main() {
    double test_cases[] = {0., 1., 100., 1.2345678, 12345.678, 3.1415, 9.115251, 99999.1234, 0.};
    char buf1[22];
    char buf2[256];
    char *buf2r = buf2+128;
    for(int i=0, n=(sizeof(test_cases)/sizeof(*test_cases))-1; i<n; ++i) {
        for(int sgn = 0; sgn<4; ++sgn) {
            memset(buf2, 255, sizeof(buf2));
            double a = test_cases[i];
            if(sgn&1) a = -a;
            double b = test_cases[i+1];
            if(sgn&2) b = -b;
            snprintf(buf1, sizeof(buf1), "{%+0.4f,%+0.4f}", a, b);
            puts(buf1);
            doformat(buf2r, buf2r+22, a, b);
            puts(buf2r);
            if(strcmp(buf2r, buf1)) {
                printf("buf1 [%s] != buf2r [%s]\n", buf1, buf2r);
            }
            for(const char *p=buf2; p<buf2r; ++p) {
                if((unsigned char)(*p)!=255) {
                    printf("unexpected %d at %d\n", *p, (int)(p-buf2));
                }
            }
            for(const char *p=buf2r+22; p<buf2 + sizeof(buf2); ++p) {
                if((unsigned char)(*p)!=255) {
                    printf("unexpected %d at %d\n", *p, (int)(p-buf2));
                }
            }
        }
    }
    return 0;

}
