diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2020-09-03 03:00:30 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2020-09-03 03:00:30 +0200 |
commit | 5172421d248250b4ab3b69eb57fd83656e23a4da (patch) | |
tree | a499d9f1dd0b74b754816884a59927b3171656fc /src/roof-read-file.c | |
parent | 7b2e6168b049be9e7852b2d364d897592eff69fc (diff) | |
download | ufo-roof-temp-5172421d248250b4ab3b69eb57fd83656e23a4da.tar.gz ufo-roof-temp-5172421d248250b4ab3b69eb57fd83656e23a4da.tar.bz2 ufo-roof-temp-5172421d248250b4ab3b69eb57fd83656e23a4da.tar.xz ufo-roof-temp-5172421d248250b4ab3b69eb57fd83656e23a4da.zip |
Diffstat (limited to 'src/roof-read-file.c')
-rw-r--r-- | src/roof-read-file.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/roof-read-file.c b/src/roof-read-file.c new file mode 100644 index 0000000..da8d51c --- /dev/null +++ b/src/roof-read-file.c @@ -0,0 +1,98 @@ +#include <stdio.h> +#include <errno.h> +#include <assert.h> +#include <stdint.h> + +#include "glib.h" + +#include "ufo-roof.h" +#include "ufo-roof-read-file.h" + +typedef struct { + RoofReadInterface iface; + + RoofConfig *cfg; + + gchar *fname; + FILE *fd; + uint8_t *buf; +} RoofReadFile; + +static void roof_read_file_free(RoofReadInterface *iface) { + RoofReadFile *reader = (RoofReadFile*)iface; + + if (reader) { + if (reader->fname) + g_free(reader->fname); + + if (reader->fd) + fclose(reader->fd); + + if (reader->buf) + free(reader->buf); + free(reader); + } +} + +static guint roof_read_file(RoofReadInterface *iface, uint8_t **buffers, GError **error) { + RoofReadFile *reader = (RoofReadFile*)iface; + RoofConfig *cfg = reader->cfg; + + assert(iface); + assert(buffers); + + size_t bytes = 0; + size_t packet_size = cfg->header_size + cfg->payload_size; + size_t expected = cfg->max_packets * packet_size; + + while ((!feof(reader->fd))&&(!ferror(reader->fd))&&(bytes < expected)) { + size_t ret = fread(reader->buf + bytes, 1, expected - bytes, reader->fd); + bytes += ret; + } + + guint packets = bytes / packet_size; + + if (ferror(reader->fd)) { + roof_network_error_with_retval(error, 0, "read failed, error %i", ferror(reader->fd)); + } else if ((feof(reader->fd))&&(bytes % packet_size)) { + roof_network_error_with_retval(error, packets, "extra data in the end of input"); + } + + *buffers = reader->buf; + return packets; +} + + +RoofReadInterface *roof_read_file_new(RoofConfig *cfg, const char *path, guint file_id, GError **error) { + RoofReadFile *reader = (RoofReadFile*)calloc(1, sizeof(RoofReadFile)); + if (!reader) roof_new_error(error, "Can't allocate RoofReadFile"); + + // FIXME: Shall we jump if max_packet_size > header+payload (or will be extra data included in the data files)? Report error for now. + if ((cfg->header_size + cfg->payload_size) != cfg->max_packet_size) + roof_new_error(error, "packet_size (%u) should be equal to max_packet_size (%u) if RoofReadFile is used", cfg->header_size + cfg->payload_size, cfg->max_packet_size); + + reader->cfg = cfg; + reader->iface.close = roof_read_file_free; + reader->iface.read =roof_read_file; + + reader->fname = g_strdup_printf(path, file_id); + if (!reader->fname) { + free(reader); + roof_new_error(error, "Can't build file name"); + } + + reader->fd = fopen(reader->fname, "rb"); + if (!reader->fd) { + g_free(reader->fname); + g_free(reader); + roof_new_error(error, "Can't open file %i at path %s", file_id, path); + } + + reader->buf = (uint8_t*)malloc(cfg->max_packets * (cfg->header_size + cfg->payload_size)); + if (!reader->buf) { + roof_read_file_free((RoofReadInterface*)reader); + roof_new_error(error, "Can't allocate file buffer"); + } + + return (RoofReadInterface*)reader; +} |