diff options
Diffstat (limited to 'src/libdisfluid/disfluid-cache-group.h')
-rw-r--r-- | src/libdisfluid/disfluid-cache-group.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/libdisfluid/disfluid-cache-group.h b/src/libdisfluid/disfluid-cache-group.h new file mode 100644 index 0000000..6f6b386 --- /dev/null +++ b/src/libdisfluid/disfluid-cache-group.h @@ -0,0 +1,130 @@ +#ifndef DISFLUID_DISFLUID_CACHE_GROUP_INCLUDED +# define DISFLUID_DISFLUID_CACHE_GROUP_INCLUDED + +# include <config.h> +# include "string-desc.h" +# include <stdbool.h> + +MAYBE_UNUSED static int +ao_cache_group_read (int fd, size_t offset, + size_t *n_entries, size_t **entry_offsets); + +MAYBE_UNUSED static int +ao_cache_group_push (int fd, size_t *offset, + size_t n_entries, const size_t *entry_offsets); + +# include "disfluid-append-only-file.h" +# include "safe-alloc.h" + +/* The cache group is organized as follows: + + - on 8 bytes, the number of entries, + - on 8 bytes, the offset of the entry array. + */ + +static int +ao_cache_group_read (int fd, + size_t offset, size_t *n_entries, size_t **entry_offsets) +{ + uint8_t header[16]; + string_desc_t header_desc = { + ._nbytes = sizeof (header), + ._data = header + }; + *n_entries = 0; + *entry_offsets = NULL; + size_t array_offset = 0; + if (ao_file_read (fd, offset, header_desc) < 0) + { + return -1; + } + for (size_t i = 0; i < 8; i++) + { + *n_entries *= 256; + *n_entries += header[i]; + } + for (size_t i = 8; i < 16; i++) + { + array_offset *= 256; + array_offset += header[i]; + } + uint8_t *array_data = NULL; + if (ALLOC_N (array_data, *n_entries * 8) < 0 + || ALLOC_N (*entry_offsets, *n_entries) < 0) + { + FREE (array_data); + FREE (*entry_offsets); + return -1; + } + string_desc_t array_desc = { + ._nbytes = *n_entries * 8, + ._data = array_data + }; + if (ao_file_read (fd, array_offset, array_desc) < 0) + { + FREE (array_data); + FREE (*entry_offsets); + return -1; + } + for (size_t i = 0; i < *n_entries; i++) + { + (*entry_offsets)[i] = 0; + for (size_t j = i * 8; j < (i + 1) * 8; j++) + { + (*entry_offsets)[i] *= 256; + (*entry_offsets)[i] += array_data[j]; + } + } + FREE (array_data); + return 0; +} + +static int +ao_cache_group_push (int fd, + size_t *offset, + size_t n_entries, const size_t *entry_offsets) +{ + uint8_t *array_data = NULL; + if (ALLOC_N (array_data, n_entries * 8) < 0) + { + return -1; + } + for (size_t i = 0; i < n_entries; i++) + { + size_t offset = entry_offsets[i]; + for (size_t j = 8 * (i + 1); j-- > 8 * i;) + { + array_data[j] = offset % 256; + offset /= 256; + } + } + string_desc_t array_desc = { + ._nbytes = n_entries * 8, + ._data = array_data + }; + size_t array_offset; + if (ao_file_push_data (fd, array_desc, &array_offset) < 0) + { + FREE (array_data); + return -1; + } + FREE (array_data); + uint8_t header_data[16] = { 0 }; + for (size_t i = 8; i-- > 0;) + { + header_data[i] = n_entries % 256; + n_entries /= 256; + } + for (size_t i = 16; i-- > 8;) + { + header_data[i] = array_offset % 256; + array_offset /= 256; + } + string_desc_t header_desc = { + ._nbytes = 16, + ._data = header_data + }; + return ao_file_push_data (fd, header_desc, offset); +} + +#endif /* DISFLUID_DISFLUID_CACHE_GROUP_INCLUDED */ |