Skip to content

Commit

Permalink
Merge pull request #82 from Gottox/feature/generic-collector
Browse files Browse the repository at this point in the history
easy: use generic collector for easy directory
  • Loading branch information
Gottox committed Aug 29, 2023
2 parents e6ce61b + 6d3cdfb commit 08b0fce
Show file tree
Hide file tree
Showing 46 changed files with 217 additions and 67 deletions.
77 changes: 17 additions & 60 deletions lib/easy/directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,86 +46,43 @@
#include "../../include/sqsh_file_private.h"
#include "../../include/sqsh_tree_private.h"

static int
directory_collector_next(void *iterator, const char **value, size_t *size) {
int rv = 0;
if (sqsh_directory_iterator_next(iterator, &rv)) {
*value = sqsh_directory_iterator_name(iterator);
*size = (size_t)sqsh_directory_iterator_name_size(iterator);
}
return rv;
}

char **
sqsh_easy_directory_list(
struct SqshArchive *archive, const char *path, int *err) {
sqsh_easy_directory_list(struct SqshArchive *archive, const char *path, int *err) {
int rv = 0;
static const uintptr_t nullptr = 0;
struct CxBuffer dir_list = {0};
struct CxBuffer dir_list_names = {0};
size_t elements = 0;
struct SqshFile *file = NULL;
struct SqshDirectoryIterator *iterator = NULL;
char **dir_list_data = NULL;
struct SqshDirectoryIterator iterator = {0};
char **list = NULL;

file = sqsh_open(archive, path, &rv);
if (rv < 0) {
goto out;
}

if (sqsh_file_type(file) != SQSH_FILE_TYPE_DIRECTORY) {
rv = -SQSH_ERROR_NOT_A_DIRECTORY;
goto out;
}

rv = cx_buffer_init(&dir_list);
if (rv < 0) {
goto out;
}
rv = cx_buffer_init(&dir_list_names);
if (rv < 0) {
goto out;
}

iterator = sqsh_directory_iterator_new(file, &rv);
rv = sqsh__directory_iterator_init(&iterator, file);
if (rv < 0) {
goto out;
}

while (sqsh_directory_iterator_next(iterator, &rv)) {
const char *name = sqsh_directory_iterator_name(iterator);
size_t name_len = sqsh_directory_iterator_name_size(iterator);
size_t index = cx_buffer_size(&dir_list_names);
char *index_ptr = (void *)index;
elements++;
rv = cx_buffer_append(&dir_list, (uint8_t *)&index_ptr, sizeof(char *));
if (rv < 0) {
goto out;
}
rv = cx_buffer_append(&dir_list_names, (uint8_t *)name, name_len);
if (rv < 0) {
goto out;
}
rv = cx_buffer_append(
&dir_list_names, (uint8_t *)&nullptr, sizeof(char));
if (rv < 0) {
goto out;
}
}

rv = cx_buffer_append(&dir_list, (uint8_t *)&nullptr, sizeof(char *));
size_t base_size = cx_buffer_size(&dir_list);

const uint8_t *names_data = cx_buffer_data(&dir_list_names);
size_t names_size = cx_buffer_size(&dir_list_names);
rv = cx_buffer_append(&dir_list, names_data, names_size);
rv = cx_collect(&list, directory_collector_next, &iterator);
if (rv < 0) {
goto out;
}

dir_list_data = (char **)cx_buffer_unwrap(&dir_list);

for (sqsh_index_t i = 0; i < elements; i++) {
dir_list_data[i] += base_size + (uintptr_t)dir_list_data;
}

out:
sqsh_directory_iterator_free(iterator);
cx_buffer_cleanup(&dir_list);
cx_buffer_cleanup(&dir_list_names);
sqsh__directory_iterator_cleanup(&iterator);
sqsh_close(file);
if (err) {
*err = rv;
}
return dir_list_data;
return list;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c65f3da22779c3e7b3935233687cd5ed017464a7d70eef65eb95a29865d37099
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ CX_NO_UNUSED int cx_lru_touch(struct CxLru *lru, size_t id);
int cx_lru_cleanup(struct CxLru *lru);

/***************************************
* primitive/reader.c
* collection/reader.c
*/

/**
Expand Down Expand Up @@ -556,6 +556,15 @@ struct CxReader {
const uint8_t *data;
};

/***************************************
* collection/collector.c
*/

typedef int (*cx_collector_next_t)(
void *iterator, const char **value, size_t *size);

int cx_collect(char ***target, cx_collector_next_t next, void *iterator);

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* @author : Enno Boland ([email protected])
* @file : iterator_collector
* @created : Tuesday Aug 29, 2023 17:27:35 CEST
*/

#include "../../include/cextras/collection.h"
#include "../../include/cextras/error.h"

int
cx_collect(char ***target, cx_collector_next_t next, void *iterator) {
int rv = 0;
static const uintptr_t nullptr = 0;
struct CxBuffer list = {0};
struct CxBuffer list_values = {0};
size_t elements = 0;
char **result = NULL;

rv = cx_buffer_init(&list);
if (rv < 0) {
goto out;
}
rv = cx_buffer_init(&list_values);
if (rv < 0) {
goto out;
}

for (;;) {
const char *value = NULL;
size_t size = 0;

rv = next(iterator, &value, &size);
if (rv < 0) {
goto out;
}
if (value == NULL) {
break;
}

size_t index = cx_buffer_size(&list_values);
char *index_ptr = (void *)index;
elements++;
rv = cx_buffer_append(&list, (uint8_t *)&index_ptr, sizeof(char *));
if (rv < 0) {
goto out;
}
rv = cx_buffer_append(&list_values, (uint8_t *)value, size);
if (rv < 0) {
goto out;
}
rv = cx_buffer_append(&list_values, (uint8_t *)&nullptr, sizeof(char));
if (rv < 0) {
goto out;
}
}

rv = cx_buffer_append(&list, (uint8_t *)&nullptr, sizeof(char *));
size_t base_size = cx_buffer_size(&list);

const uint8_t *values_data = cx_buffer_data(&list_values);
size_t values_size = cx_buffer_size(&list_values);

rv = cx_buffer_append(&list, values_data, values_size);
if (rv < 0) {
goto out;
}

result = (char **)cx_buffer_unwrap(&list);
for (cx_index_t i = 0; i < elements; i++) {
result[i] += base_size + (uintptr_t)result;
}
*target = result;

out:
cx_buffer_cleanup(&list);
cx_buffer_cleanup(&list_values);
return rv;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
collection_src = files(
'buffer.c',
'collector.c',
'lru.c',
'rc_hash_map.c',
'rc_map.c',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* BSD 2-Clause License
*
* Copyright (c) 2023, Enno Boland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/**
* @author Enno Boland ([email protected])
* @file rc_map.c
*/

#include <assert.h>
#include <cextras/collection.h>
#include <cextras/types.h>
#include <stdlib.h>
#include <string.h>
#include <testlib.h>

#define LENGTH(x) (sizeof(x) / sizeof(*x))

struct TestCollectIter {
cx_index_t index;
char **array;
size_t size;
int rv;
};

static int
test_collect_next(void *iter, const char **value, size_t *size) {
struct TestCollectIter *i = iter;
if (i->index >= i->size) {
return i->rv;
}
*value = i->array[i->index];
*size = strlen(i->array[i->index]);
i->index++;
return i->rv;
}

static void
collector(void) {
int rv = 0;
char *values[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
char **target = NULL;
struct TestCollectIter iter = {
.index = 0,
.array = values,
.size = LENGTH(values),
};

rv = cx_collect(&target, test_collect_next, &iter);
assert(rv == 0);

for (size_t i = 0; i < LENGTH(values); i++) {
assert(strcmp(values[i], target[i]) == 0);
}
assert(target[LENGTH(values)] == NULL);
free(target);
}

static void
collector_fail(void) {
int rv = 0;
char *values[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
char **target = NULL;
struct TestCollectIter iter = {
.index = 0,
.array = values,
.size = LENGTH(values),
.rv = -1,
};

rv = cx_collect(&target, test_collect_next, &iter);
assert(rv == -1);
assert(target == NULL);
}

DECLARE_TESTS
TEST(collector)
TEST(collector_fail)
END_TESTS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tests = [
'concurrency/threadpool_test.c',
'concurrency/future_test.c',
'collection/buffer_test.c',
'collection/collector.c',
'collection/lru_test.c',
'collection/rc_hash_map_test.c',
'collection/rc_map_test.c',
Expand Down

This file was deleted.

8 changes: 4 additions & 4 deletions subprojects/cextras.wrap
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[wrap-file]
directory = cextras-990106e5492c382669a7238a2e291d655c19fedb
directory = cextras-04517a4939153026a9ccdf2778ed11403be6f4e7

source_url = https://github.com/Gottox/cextras/archive/990106e5492c382669a7238a2e291d655c19fedb.tar.gz
source_filename = cextras-990106e5492c382669a7238a2e291d655c19fedb.tar.gz
source_hash = fdfedf3e143f3dfeb1ca6ae970ba52f94fa5929742b0196f6b784f66ba20d2cb
source_url = https://github.com/Gottox/cextras/archive/04517a4939153026a9ccdf2778ed11403be6f4e7.tar.gz
source_filename = cextras-04517a4939153026a9ccdf2778ed11403be6f4e7.tar.gz
source_hash = 572e6fc8d9bd17367926a36583a2b06974b7236ad40d571ba30f471359c1b78e

[provide]
cextras=cextras_dep
Expand Down
2 changes: 1 addition & 1 deletion test/easy/directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ list_two_files(void) {
/* inode */
[INODE_TABLE_OFFSET] = METABLOCK_HEADER(0, 1024),
INODE_HEADER(1, 0, 0, 0, 0, 1),
INODE_BASIC_DIR(0, 1024, 0, 0),
INODE_BASIC_DIR(0, 33, 0, 0),
[INODE_TABLE_OFFSET+2+128] =
INODE_HEADER(3, 0, 0, 0, 0, 2),
INODE_BASIC_SYMLINK(3),
Expand Down

0 comments on commit 08b0fce

Please sign in to comment.