hex-editor/src/source.c

109 lines
2.4 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);
s->no_origin = false;
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)
{
if(!s || !s->intf->size)
return 0;
int base_size = s->intf->size(s->cookie);
/* Add the size difference from the front buffer */
return max(0, base_size - s->buf_segment_size + s->buf->data_size);
}
bool source_dirty(source_t *s)
{
return s && s->intf->dirty && s->intf->dirty(s->cookie);
}
ssize_t source_load(source_t *s, off_t offset, size_t segment_size)
{
if(!s || !buffer_resize(s->buf, segment_size))
return -1;
ssize_t rc = s->intf->read(s->cookie, s->buf->mem, offset, segment_size);
if(rc < 0)
return -1;
s->buf_offset = offset;
s->buf_segment_size = rc;
s->buf->data_size = rc;
return rc;
}
bool source_requires_load(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;
return true;
}
void source_ensure_loaded(source_t *s, off_t offset, int n)
{
if(!source_requires_load(s, offset, n))
return;
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);
}
bool source_save_front_buffer(source_t *s)
{
if(!s || !s->intf->write)
return false;
return s->intf->write(s->cookie, s->buf->mem, s->buf->data_size,
s->buf_offset, s->buf_segment_size);
}
bool source_save(source_t *s, char const *outfile)
{
return s && s->intf->save && s->intf->save(s->cookie, outfile);
}
void source_free(source_t *s)
{
if(!s)
return;
if(s->intf && s->cookie)
s->intf->close(s->cookie);
free(s->origin);
free(s);
}