summaryrefslogtreecommitdiff
path: root/src/libdisfluid/disfluid-cache-group.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdisfluid/disfluid-cache-group.h')
-rw-r--r--src/libdisfluid/disfluid-cache-group.h130
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 */