apfl/src/format.c
Laria Carolin Chabowski 145fcddbed format: Use %G to print numbers
This avoids appending .000[...] on integer numbers
2022-10-30 22:51:51 +01:00

116 lines
2.5 KiB
C

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "apfl.h"
#include "format.h"
#define TRY FMT_TRY
static bool
write(struct apfl_format_writer w, const char *buf, size_t len)
{
return len == 0
? true
: w.write(w.opaque, buf, len);
}
static bool
write_file(void *opaque, const char *buf, size_t len)
{
FILE *f = opaque;
return fwrite(buf, len, 1, f) == 1;
}
static bool
write_string(void *opaque, const char *buf, size_t len)
{
struct apfl_string_builder *sb = opaque;
return apfl_string_builder_append(sb, (struct apfl_string_view) {.bytes = buf, .len = len});
}
struct apfl_format_writer
apfl_format_file_writer(FILE *f)
{
return (struct apfl_format_writer) {
.write = write_file,
.opaque = f,
};
}
struct apfl_format_writer
apfl_format_string_writer(struct apfl_string_builder *sb)
{
return (struct apfl_format_writer) {
.write = write_string,
.opaque = sb,
};
}
bool
apfl_format_put_string_view(struct apfl_format_writer w, struct apfl_string_view sv)
{
return write(w, sv.bytes, sv.len);
}
#define PUT_INT_BUFSIZE 21 // ceil(log10(2**64)) + 1
bool
apfl_format_put_int(struct apfl_format_writer w, int i)
{
char buf[PUT_INT_BUFSIZE];
size_t len = snprintf(buf, PUT_INT_BUFSIZE, "%d", i);
assert(len < PUT_INT_BUFSIZE);
return write(w, buf, len);
}
bool
apfl_format_put_char(struct apfl_format_writer w, char c)
{
return write(w, &c, 1);
}
#define PUT_HEXBYTE_BUFSIZE 3
bool
apfl_format_put_hexbyte(struct apfl_format_writer w, unsigned char c)
{
char buf[PUT_HEXBYTE_BUFSIZE];
size_t len = snprintf(buf, PUT_HEXBYTE_BUFSIZE, "%x", (unsigned) c);
assert(len < PUT_HEXBYTE_BUFSIZE);
return write(w, buf, len);
}
bool
apfl_format_put_pos(struct apfl_format_writer w, struct apfl_position pos)
{
TRY(apfl_format_put_int(w, pos.line));
TRY(apfl_format_put_string(w, ":"));
TRY(apfl_format_put_int(w, pos.col));
return true;
}
bool
apfl_format_put_indent(struct apfl_format_writer w, unsigned indent)
{
while (indent--) {
TRY(apfl_format_put_string(w, " "));
}
return true;
}
#define PUT_NUMBER_BUFSIZE 100 // Arbitrarily chosen ¯\_(ツ)_/¯
bool
apfl_format_put_number(struct apfl_format_writer w, apfl_number number)
{
char buf[PUT_NUMBER_BUFSIZE];
size_t len = snprintf(buf, PUT_NUMBER_BUFSIZE, "%.12G", number);
TRY(write(w, buf, len));
if (len >= PUT_NUMBER_BUFSIZE) {
TRY(apfl_format_put_string(w, "[...]"));
}
return true;
}