#include #include #include #include #include "apfl.h" #include "format.h" #define WRITE(w, buf, len) w.write(w.opaque, buf, len) #define TRY FMT_TRY 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, "%f", number); TRY(WRITE(w, buf, len)); if (len >= PUT_NUMBER_BUFSIZE) { TRY(apfl_format_put_string(w, "[...]")); } return true; }