Skip to content

Commit

Permalink
reader: move skip to the implementors.
Browse files Browse the repository at this point in the history
This allows implementors of the generic reader to implement optimized
skip functions.
  • Loading branch information
Gottox committed Aug 21, 2023
1 parent d2aa65f commit 434c890
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 38 deletions.
1 change: 1 addition & 0 deletions include/sqsh_reader_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ extern "C" {

struct SqshReaderIteratorImpl {
bool (*next)(void *iterator, size_t desired_size, int *err);
int (*skip)(void *iterator, sqsh_index_t *offset, size_t desired_size);
const uint8_t *(*data)(const void *iterator);
size_t (*size)(const void *iterator);
};
Expand Down
22 changes: 22 additions & 0 deletions lib/file/file_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ static bool
file_iterator_next(void *iterator, size_t desired_size, int *err) {
return sqsh_file_iterator_next(iterator, desired_size, err);
}
static int
file_iterator_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) {
int rv = 0;

size_t current_size = sqsh_file_iterator_size(iterator);
while (current_size <= *offset) {
*offset -= current_size;
bool has_next = sqsh_file_iterator_next(iterator, desired_size, &rv);
if (rv < 0) {
goto out;
} else if (!has_next) {
rv = -SQSH_ERROR_OUT_OF_BOUNDS;
goto out;
}
current_size = sqsh_file_iterator_size(iterator);
}

rv = 0;
out:
return rv;
}
static const uint8_t *
file_iterator_data(const void *iterator) {
return sqsh_file_iterator_data(iterator);
Expand All @@ -54,6 +75,7 @@ file_iterator_size(const void *iterator) {

static const struct SqshReaderIteratorImpl file_reader_impl = {
.next = file_iterator_next,
.skip = file_iterator_skip,
.data = file_iterator_data,
.size = file_iterator_size,
};
Expand Down
23 changes: 23 additions & 0 deletions lib/mapper/map_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ map_iterator_next(void *iterator, size_t desired_size, int *err) {
(void)desired_size;
return sqsh__map_iterator_next(iterator, err);
}
static int
map_iterator_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) {
(void)desired_size;
int rv = 0;

size_t current_size = sqsh__map_iterator_size(iterator);
while (current_size <= *offset) {
*offset -= current_size;
bool has_next = sqsh__map_iterator_next(iterator, &rv);
if (rv < 0) {
goto out;
} else if (!has_next) {
rv = -SQSH_ERROR_OUT_OF_BOUNDS;
goto out;
}
current_size = sqsh__map_iterator_size(iterator);
}

rv = 0;
out:
return rv;
}
static const uint8_t *
map_iterator_data(const void *iterator) {
return sqsh__map_iterator_data(iterator);
Expand All @@ -52,6 +74,7 @@ map_iterator_size(const void *iterator) {

static const struct SqshReaderIteratorImpl map_reader_impl = {
.next = map_iterator_next,
.skip = map_iterator_skip,
.data = map_iterator_data,
.size = map_iterator_size,
};
Expand Down
23 changes: 23 additions & 0 deletions lib/metablock/metablock_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ metablock_iterator_next(void *iterator, size_t desired_size, int *err) {
(void)desired_size;
return sqsh__metablock_iterator_next(iterator, err);
}
static int
metablock_iterator_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) {
(void)desired_size;
int rv = 0;

size_t current_size = sqsh__metablock_iterator_size(iterator);
while (current_size <= *offset) {
*offset -= current_size;
bool has_next = sqsh__metablock_iterator_next(iterator, &rv);
if (rv < 0) {
goto out;
} else if (!has_next) {
rv = -SQSH_ERROR_OUT_OF_BOUNDS;
goto out;
}
current_size = sqsh__metablock_iterator_size(iterator);
}

rv = 0;
out:
return rv;
}
static const uint8_t *
metablock_iterator_data(const void *iterator) {
return sqsh__metablock_iterator_data(iterator);
Expand All @@ -56,6 +78,7 @@ metablock_iterator_size(const void *iterator) {

static const struct SqshReaderIteratorImpl metablock_reader_impl = {
.next = metablock_iterator_next,
.skip = metablock_iterator_skip,
.data = metablock_iterator_data,
.size = metablock_iterator_size,
};
Expand Down
39 changes: 1 addition & 38 deletions lib/reader/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,6 @@ reader_iterator_next(struct SqshReader *reader, size_t desired_size, int *err) {
}
}

/**
* @brief Skips the iterator until the offset is reached.
*
* This is a naiv implementation that just calls next until the offset is
* reached.
*
* TODO: Implement a iterator specific skip function.
*
* @param reader The reader
* @param offset The offset
* @param[in] desired_size The desired size
*
* @return 0 on success, negative on error.
*/
static int
reader_iterator_skip(
struct SqshReader *reader, sqsh_index_t *offset, size_t desired_size) {
int rv = 0;
void *iterator = reader->iterator;
const struct SqshReaderIteratorImpl *impl = reader->iterator_impl;

size_t current_size = impl->size(iterator);

while (current_size <= *offset) {
*offset -= current_size;
reader_iterator_next(reader, desired_size, &rv);
if (rv < 0) {
goto out;
}
current_size = impl->size(iterator);
}

rv = 0;
out:
return rv;
}

int
sqsh__reader_init(
struct SqshReader *reader,
Expand Down Expand Up @@ -197,7 +160,7 @@ handle_mapped(struct SqshReader *reader, sqsh_index_t offset, size_t size) {
goto out;
}

rv = reader_iterator_skip(reader, &offset, size);
rv = impl->skip(iterator, &offset, size);
if (rv < 0) {
goto out;
}
Expand Down
23 changes: 23 additions & 0 deletions test/reader/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,31 @@ test_iter_next(void *data, size_t desired_size, int *err) {
return true;
}

static int
test_iter_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) {
int rv = 0;

size_t current_size = test_iter_size(iterator);
while (current_size <= *offset) {
*offset -= current_size;
bool has_next = test_iter_next(iterator, desired_size, &rv);
if (rv < 0) {
goto out;
} else if (!has_next) {
rv = -SQSH_ERROR_OUT_OF_BOUNDS;
goto out;
}
current_size = test_iter_size(iterator);
}

rv = 0;
out:
return rv;
}

static const struct SqshReaderIteratorImpl test_iter = {
.next = test_iter_next,
.skip = test_iter_skip,
.data = test_iter_data,
.size = test_iter_size,
};
Expand Down

0 comments on commit 434c890

Please sign in to comment.