#include "source.h" #include #include #include source_t *source_open(source_intf_t *intf, void *cookie, char const *origin) { source_t *s = calloc(1, sizeof *s); if(!s) goto fail; s->origin = strdup(origin); if(!s->origin) goto fail; s->buf = buffer_create(0, 1024); if(!s->buf) goto fail; s->intf = intf; s->cookie = cookie; return s; fail: source_free(s); return NULL; } size_t source_size(source_t *s) { return s && s->intf && s->intf->size ? s->intf->size(s->cookie) : 0; } ssize_t source_load(source_t *s, off_t offset, size_t segment_size) { if(!s || !buffer_resize(s->buf, segment_size)) return -1; s->buf_offset = offset; ssize_t rc = s->intf->read(s->cookie, s->buf->mem, offset, segment_size); if(rc < 0) return -1; s->buf->data_size = rc; return rc; } bool source_ensure_loaded(source_t *s, off_t offset, int n) { if(!s) return false; if(offset >= s->buf_offset && offset + n <= (int)(s->buf_offset + s->buf->data_size)) return false; int s_size = source_size(s); int max_offset = max(s_size - n, 0); /* Load 1 block before the current position, 1 after */ off_t new_s_offset = offset - s->buf->block_size; new_s_offset = max(0, min(new_s_offset, max_offset)); /* Use 2 blocks of buffer by default */ source_load(s, new_s_offset, 2 * s->buf->block_size); return true; } void source_free(source_t *s) { if(!s) return; if(s->intf && s->cookie) s->intf->close(s->cookie); free(s->origin); free(s); }