hex-editor/src/source.c

78 lines
1.6 KiB
C

#include "source.h"
#include <stdlib.h>
#include <string.h>
#include <gint/defs/util.h>
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);
}