Skip to content

Commit

Permalink
file_iterator: implement a _copy() function
Browse files Browse the repository at this point in the history
This function creates a copy of the iterator that has the same state as
the original iterator.
  • Loading branch information
Gottox committed Aug 19, 2024
1 parent 13c79fd commit 2339950
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 5 deletions.
14 changes: 14 additions & 0 deletions common/include/sqsh_reader_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__reader_init(
struct SqshReader *reader,
const struct SqshReaderIteratorImpl *iterator_impl, void *iterator);

/**
* @internal
* @memberof SqshReader
* @brief Creates a copy of an extractor reader.
*
* @param[out] target The reader to copy to.
* @param[in] source The reader to copy from.
*
* @return 0 on success, a negative value on error.
*/
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__reader_copy(
struct SqshReader *target, const struct SqshReader *source,
void *copied_iterator);

/**
* @internal
* @memberof SqshReader
Expand Down
43 changes: 43 additions & 0 deletions common/src/reader/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,49 @@ sqsh__reader_init(
return cx_buffer_init(&reader->buffer);
}

int
sqsh__reader_copy(

Check warning on line 69 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L69

Added line #L69 was not covered by tests
struct SqshReader *target, const struct SqshReader *source,
void *copied_iterator) {
int rv = 0;

Check warning on line 72 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L72

Added line #L72 was not covered by tests

target->iterator = copied_iterator;
target->iterator_impl = source->iterator_impl;
target->iterator_offset = source->iterator_offset;
target->offset = source->offset;
const uint8_t *buffer_data = cx_buffer_data(&source->buffer);
const size_t buffer_size = cx_buffer_size(&source->buffer);
rv = cx_buffer_init(&target->buffer);

Check warning on line 80 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L74-L80

Added lines #L74 - L80 were not covered by tests
if (rv < 0) {
goto out;

Check warning on line 82 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L82

Added line #L82 was not covered by tests
}
rv = cx_buffer_append(

Check warning on line 84 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L84

Added line #L84 was not covered by tests
&target->buffer, cx_buffer_data(&source->buffer),
cx_buffer_size(&source->buffer));
if (rv < 0) {
goto out;

Check warning on line 88 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L88

Added line #L88 was not covered by tests
}
buffer_data = cx_buffer_data(&target->buffer);
const uint8_t *iterator_data = target->iterator_impl->data(copied_iterator);
const size_t iterator_size = target->iterator_impl->size(copied_iterator);
const uint8_t *data = source->data;

Check warning on line 93 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L90-L93

Added lines #L90 - L93 were not covered by tests

if (data == NULL) {
target->data = NULL;

Check warning on line 96 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L96

Added line #L96 was not covered by tests
} else if (data >= buffer_data && data < buffer_data + buffer_size) {
target->data = &buffer_data[data - buffer_data];

Check warning on line 98 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L98

Added line #L98 was not covered by tests
} else if (data >= iterator_data && data < iterator_data + iterator_size) {
target->data = &iterator_data[data - iterator_data];

Check warning on line 100 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L100

Added line #L100 was not covered by tests
} else {
rv = -SQSH_ERROR_INTERNAL;
goto out;

Check warning on line 103 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L102-L103

Added lines #L102 - L103 were not covered by tests
}
target->size = source->size;

Check warning on line 105 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L105

Added line #L105 was not covered by tests

out:
return rv;

Check warning on line 108 in common/src/reader/reader.c

View check run for this annotation

Codecov / codecov/patch

common/src/reader/reader.c#L107-L108

Added lines #L107 - L108 were not covered by tests
}

/**
* @brief copies data from the iterator to the buffer until the buffer
* reaches the desired size.
Expand Down
29 changes: 27 additions & 2 deletions libsqsh/include/sqsh_extract_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,10 @@ struct SqshExtractManager {
/**
* @privatesection
*/
struct CxRcRadixTree cache;
const struct SqshExtractorImpl *extractor_impl;
uint32_t block_size;
struct SqshMapManager *map_manager;
struct CxRcRadixTree cache;
uint32_t block_size;
struct CxLru lru;
sqsh__mutex_t lock;
};
Expand Down Expand Up @@ -215,6 +215,19 @@ SQSH_NO_EXPORT int sqsh__extract_manager_uncompress(
struct SqshExtractManager *manager, const struct SqshMapReader *reader,
const struct CxBuffer **target);

/**
* @internal
* @memberof SqshExtractManager
* @brief Retains a buffer retrieved by sqsh__extract_manager_uncompress.
*
* @param[in] manager The manager to use.
* @param[out] buffer The buffer that needs to be retained
*
* @return 0 on success, a negative value on error.
*/
SQSH_NO_EXPORT int sqsh__extract_manager_retain_buffer(
struct SqshExtractManager *manager, const struct CxBuffer *buffer);

/**
* @internal
* @memberof SqshExtractManager
Expand Down Expand Up @@ -272,6 +285,18 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__extract_view_init(
struct SqshExtractView *view, struct SqshExtractManager *manager,
const struct SqshMapReader *reader);

/**
* @internal
* @memberof SqshExtractView
* @brief Creates a copy of an extractor view.
*
* @param[out] target The view to copy to.
* @param[in] source The view to copy from.
*
* @return 0 on success, a negative value on error.
*/
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__extract_view_copy(
struct SqshExtractView *target, const struct SqshExtractView *source);
/**
* @internal
* @memberof SqshExtractView
Expand Down
16 changes: 16 additions & 0 deletions libsqsh/include/sqsh_file_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ single file.
SQSH_NO_EXPORT int sqsh__fragment_view_init(
struct SqshFragmentView *view, const struct SqshFile *file);

/**
* @internal
* @memberof SqshFragmentView
* @brief Creates a copy of an fragment view.
*
* @param[out] target The view to copy to.
* @param[in] source The view to copy from.
*
* @return 0 on success, a negative value on error.
*/
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__fragment_view_copy(
struct SqshFragmentView *target, const struct SqshFragmentView *source);

/**
* @internal
* @memberof SqshFragmentView
Expand Down Expand Up @@ -270,6 +283,9 @@ struct SqshFile {
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__file_init(
struct SqshFile *context, struct SqshArchive *sqsh, uint64_t inode_ref);

SQSH_NO_EXPORT SQSH_NO_UNUSED int
sqsh__file_copy(struct SqshFile *context, const struct SqshFile *other);

/**
* @memberof SqshFile
* @brief sets the parent inode reference.
Expand Down
30 changes: 28 additions & 2 deletions libsqsh/include/sqsh_mapper_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,12 @@ struct SqshMapIterator {
/**
* @privatesection
*/
sqsh_index_t next_index;
uint64_t segment_count;
struct SqshMapManager *map_manager;
const struct SqshMapSlice *mapping;
const uint8_t *data;
size_t size;
sqsh_index_t next_index;
uint64_t segment_count;
};

/**
Expand All @@ -288,6 +288,19 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_iterator_init(
struct SqshMapIterator *iterator, struct SqshMapManager *manager,
uint64_t address);

/**
* @internal
* @memberof SqshMapIterator
* @brief Copies the content of a iterator to another iterator
*
* @param target The iterator to copy to
* @param source The iterator to copy from
*
* @return 0 on success, negative on error
*/
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_iterator_copy(
struct SqshMapIterator *target, const struct SqshMapIterator *source);

/**
* @internal
* @memberof SqshMapIterator
Expand Down Expand Up @@ -394,6 +407,19 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_reader_init(
struct SqshMapReader *reader, struct SqshMapManager *mapper,
const uint64_t start_address, uint64_t upper_limit);

/**
* @internal
* @memberof SqshMapReader
* @brief Copies the content of a reader to another reader
*
* @param target The reader to copy to
* @param source The reader to copy from
*
* @return 0 on success, negative on error
*/
SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_reader_copy(
struct SqshMapReader *target, const struct SqshMapReader *source);

/**
* @internal
* @memberof SqshMapReader
Expand Down
7 changes: 7 additions & 0 deletions libsqsh/src/extract/extract_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ sqsh__extract_manager_uncompress(
return rv;
}

int
sqsh__extract_manager_retain_buffer(

Check warning on line 176 in libsqsh/src/extract/extract_manager.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_manager.c#L176

Added line #L176 was not covered by tests
struct SqshExtractManager *manager, const struct CxBuffer *buffer) {
cx_rc_radix_tree_retain_value(&manager->cache, (void *)buffer);
return 0;

Check warning on line 179 in libsqsh/src/extract/extract_manager.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_manager.c#L178-L179

Added lines #L178 - L179 were not covered by tests
}

int
sqsh__extract_manager_release(
struct SqshExtractManager *manager, uint64_t address) {
Expand Down
22 changes: 22 additions & 0 deletions libsqsh/src/extract/extract_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ sqsh__extract_view_init(
return rv;
}

int
sqsh__extract_view_copy(

Check warning on line 63 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L63

Added line #L63 was not covered by tests
struct SqshExtractView *target, const struct SqshExtractView *source) {
int rv = 0;

Check warning on line 65 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L65

Added line #L65 was not covered by tests

target->manager = source->manager;

Check warning on line 67 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L67

Added line #L67 was not covered by tests
if (source->buffer) {
rv = sqsh__extract_manager_retain_buffer(
source->manager, source->buffer);

Check warning on line 70 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L69-L70

Added lines #L69 - L70 were not covered by tests
if (rv < 0) {
goto out;

Check warning on line 72 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L72

Added line #L72 was not covered by tests
}
}
target->buffer = source->buffer;
target->size = source->size;
out:

Check warning on line 77 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L75-L77

Added lines #L75 - L77 were not covered by tests
if (rv < 0) {
sqsh__extract_view_cleanup(target);

Check warning on line 79 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L79

Added line #L79 was not covered by tests
}
return rv;

Check warning on line 81 in libsqsh/src/extract/extract_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/extract/extract_view.c#L81

Added line #L81 was not covered by tests
}

const uint8_t *
sqsh__extract_view_data(const struct SqshExtractView *view) {
return cx_buffer_data(view->buffer);
Expand Down
32 changes: 32 additions & 0 deletions libsqsh/src/file/file_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,38 @@ sqsh__file_iterator_init(
return rv;
}

int
sqsh__file_iterator_copy(

Check warning on line 94 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L94

Added line #L94 was not covered by tests
struct SqshFileIterator *target,
const struct SqshFileIterator *source) {
int rv = 0;
target->file = source->file;
target->compression_manager = source->compression_manager;
rv = sqsh__map_reader_copy(&target->map_reader, &source->map_reader);

Check warning on line 100 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L97-L100

Added lines #L97 - L100 were not covered by tests
if (rv < 0) {
goto out;

Check warning on line 102 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L102

Added line #L102 was not covered by tests
}
rv = sqsh__extract_view_copy(&target->extract_view, &source->extract_view);

Check warning on line 104 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L104

Added line #L104 was not covered by tests
if (rv < 0) {
goto out;

Check warning on line 106 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L106

Added line #L106 was not covered by tests
}
rv = sqsh__fragment_view_copy(

Check warning on line 108 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L108

Added line #L108 was not covered by tests
&target->fragment_view, &source->fragment_view);
if (rv < 0) {
goto out;

Check warning on line 111 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L111

Added line #L111 was not covered by tests
}
target->sparse_size = source->sparse_size;
target->block_size = source->block_size;
target->block_index = source->block_index;
target->data = source->data;
target->size = source->size;
out:

Check warning on line 118 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L113-L118

Added lines #L113 - L118 were not covered by tests
if (rv < 0) {
sqsh__file_iterator_cleanup(target);

Check warning on line 120 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L120

Added line #L120 was not covered by tests
}
return rv;

Check warning on line 122 in libsqsh/src/file/file_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/file_iterator.c#L122

Added line #L122 was not covered by tests
}

struct SqshFileIterator *
sqsh_file_iterator_new(const struct SqshFile *file, int *err) {
SQSH_NEW_IMPL(sqsh__file_iterator_init, struct SqshFileIterator, file);
Expand Down
42 changes: 42 additions & 0 deletions libsqsh/src/file/fragment_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <sqsh_archive_private.h>
#include <sqsh_common_private.h>
#include <sqsh_error.h>
#include <sys/types.h>

static int
apply_fragment(
Expand Down Expand Up @@ -156,6 +157,47 @@ sqsh__fragment_view_init(
return rv;
}

int
sqsh__fragment_view_copy(

Check warning on line 161 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L161

Added line #L161 was not covered by tests
struct SqshFragmentView *target,
const struct SqshFragmentView *source) {
int rv = 0;
target->fragment_table = source->fragment_table;
rv = sqsh__map_reader_copy(&target->map_reader, &source->map_reader);

Check warning on line 166 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L164-L166

Added lines #L164 - L166 were not covered by tests
if (rv < 0) {
goto out;

Check warning on line 168 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L168

Added line #L168 was not covered by tests
}
rv = sqsh__extract_view_copy(&target->extract_view, &source->extract_view);

Check warning on line 170 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L170

Added line #L170 was not covered by tests
if (rv < 0) {
goto out;

Check warning on line 172 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L172

Added line #L172 was not covered by tests
}
const uint8_t *map_data = sqsh__map_reader_data(&target->map_reader);
size_t map_size = sqsh__map_reader_size(&target->map_reader);

Check warning on line 175 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L174-L175

Added lines #L174 - L175 were not covered by tests
const uint8_t *extract_data =
sqsh__extract_view_data(&target->extract_view);
size_t extract_size = sqsh__extract_view_size(&target->extract_view);

Check warning on line 178 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L177-L178

Added lines #L177 - L178 were not covered by tests

// Check if the data field is within the map or extract data
// and adjust the pointer accordingly
if (source->data >= map_data &&
(size_t)(source->data - map_data) < map_size) {
target->data = &map_data[source->data - map_data];
} else if (

Check warning on line 185 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L184-L185

Added lines #L184 - L185 were not covered by tests
source->data >= extract_data &&
(size_t)(source->data - extract_data) < extract_size) {
target->data = &extract_data[source->data - extract_data];

Check warning on line 188 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L188

Added line #L188 was not covered by tests
} else {
rv = -SQSH_ERROR_INVALID_ARGUMENT;
goto out;

Check warning on line 191 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L190-L191

Added lines #L190 - L191 were not covered by tests
}
target->size = source->size;
out:

Check warning on line 194 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L193-L194

Added lines #L193 - L194 were not covered by tests
if (rv < 0) {
sqsh__fragment_view_cleanup(target);

Check warning on line 196 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L196

Added line #L196 was not covered by tests
}
return rv;

Check warning on line 198 in libsqsh/src/file/fragment_view.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/file/fragment_view.c#L198

Added line #L198 was not covered by tests
}

const uint8_t *
sqsh__fragment_view_data(const struct SqshFragmentView *view) {
return view->data;
Expand Down
25 changes: 25 additions & 0 deletions libsqsh/src/mapper/map_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ sqsh__map_iterator_init(
return 0;
}

int
sqsh__map_iterator_copy(

Check warning on line 72 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L72

Added line #L72 was not covered by tests
struct SqshMapIterator *target, const struct SqshMapIterator *source) {
int rv = 0;
target->map_manager = source->map_manager;

Check warning on line 75 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L74-L75

Added lines #L74 - L75 were not covered by tests
// TODO
// rv = sqsh__map_slice_copy(target->mapping, source->mapping);
if (rv < 0) {
goto out;

Check warning on line 79 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L79

Added line #L79 was not covered by tests
}
target->mapping = NULL;
target->next_index = source->next_index;
target->segment_count = source->segment_count;

Check warning on line 83 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L81-L83

Added lines #L81 - L83 were not covered by tests
if (source->data != NULL) {
target->data = sqsh__map_slice_data(source->mapping);
target->size = sqsh__map_slice_size(source->mapping);

Check warning on line 86 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L85-L86

Added lines #L85 - L86 were not covered by tests
} else {
target->data = NULL;
target->size = 0;

Check warning on line 89 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L88-L89

Added lines #L88 - L89 were not covered by tests
}

out:
return rv;

Check warning on line 93 in libsqsh/src/mapper/map_iterator.c

View check run for this annotation

Codecov / codecov/patch

libsqsh/src/mapper/map_iterator.c#L92-L93

Added lines #L92 - L93 were not covered by tests
}

int
sqsh__map_iterator_skip(struct SqshMapIterator *iterator, uint64_t *offset) {
int rv = 0;
Expand Down
Loading

0 comments on commit 2339950

Please sign in to comment.