#include // bool #include // fscanf() #include // strerror() #include // errno #include "util.h" #include "km.h" #define FAIL(...) do { \ if (cbs && cbs->on_error) { \ char buf[1024]; \ snprintf(buf, sizeof(buf), __VA_ARGS__); \ cbs->on_error(buf, cb_data); \ } \ return false; \ } while (0) _Bool km_load( FILE * const fh, const km_load_cbs_t * const cbs, void * const cb_data ) { // read shape km_shape_t shape = { 0, 0 }; if (fscanf(fh, "%zu %zu", &(shape.num_floats), &(shape.num_ints)) != 2) { FAIL("shape fscanf() failed: %s", strerror(errno)); } if (cbs && cbs->on_shape) { // emit shape if (!cbs->on_shape(&shape, cb_data)) { // return failure return false; } } // alloc floats buffer float *floats = NULL; if (shape.num_floats > 0) { floats = malloc(sizeof(float) * shape.num_floats); if (!floats) { FAIL("floats malloc() failed: %s", strerror(errno)); } } // alloc ints buffer int *ints = NULL; if (shape.num_ints > 0) { ints = malloc(sizeof(int) * shape.num_ints); if (!ints) { FAIL("ints malloc() failed: %s", strerror(errno)); } } for (size_t row = 0; !feof(fh); row++) { for (size_t i = 0; i < shape.num_floats; i++) { if (fscanf(fh, " %f ", floats + i) != 1) { FAIL("[%zu, %zu] float fscanf() failed: %s", row, i, strerror(errno)); } } // read ints for (size_t i = 0; i < shape.num_ints; i++) { if (fscanf(fh, " %d ", ints + i) != 1) { FAIL("[%zu, %zu] int fscanf() failed: %s", row, i, strerror(errno)); } } if (cbs && cbs->on_row) { // emit row if (!cbs->on_row(floats, ints, cb_data)) { // return failure return false; } } } if (shape.num_floats > 0) { // free float buffer free(floats); } if (shape.num_ints > 0) { // free int buffer free(ints); } // return success return true; } _Bool km_load_path( const char * const path, const km_load_cbs_t * const cbs, void * const cb_data ) { // open file FILE *fh = fopen(path, "rb"); if (!fh) { FAIL("fopen(\"%s\") failed: %s", path, strerror(errno)); } // load file, get result const bool r = km_load(fh, cbs, cb_data); // close file fclose(fh); // return result return r; }