diff options
Diffstat (limited to 'apps/tagdb/array_buffer.h')
-rw-r--r-- | apps/tagdb/array_buffer.h | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/apps/tagdb/array_buffer.h b/apps/tagdb/array_buffer.h new file mode 100644 index 0000000000..6dccefe917 --- /dev/null +++ b/apps/tagdb/array_buffer.h | |||
@@ -0,0 +1,159 @@ | |||
1 | #ifndef __ARRAY_BUFFER_H__ | ||
2 | #define __ARRAY_BUFFER_H__ | ||
3 | |||
4 | #include "config.h" | ||
5 | #include <stdio.h> | ||
6 | #include <stdint.h> | ||
7 | |||
8 | struct array_buffer { | ||
9 | uint32_t count; // how much items doe we have? | ||
10 | |||
11 | union entry { | ||
12 | void* mem; | ||
13 | long file_offset; | ||
14 | } *array; // where is the data? | ||
15 | // This array will always point to the same data | ||
16 | // after sorting the position of the data may be canged | ||
17 | // but this array will also be canged accordingly | ||
18 | |||
19 | uint32_t *sort; // In what order should we put the entries on disk? | ||
20 | |||
21 | char* file_name; // filename | ||
22 | FILE *fd; // file where entries are being kept. (NULL if in mem) | ||
23 | |||
24 | int (*cmp)(const void *a, const void *b); // compare a to b, should return: | ||
25 | // a < b ==> <0 | ||
26 | // a = b ==> 0 | ||
27 | // a > b ==> >0 | ||
28 | |||
29 | int (*serialize)(FILE *fd, const void *e); // serialize e into fd | ||
30 | int (*unserialize)(void **e, FILE *fd); // unserialize the entry in fd | ||
31 | |||
32 | uint32_t (*get_length)(const void *size); // get's the length | ||
33 | int (*write)(FILE *fd, void *e, const void *size); // write e to file | ||
34 | |||
35 | int (*destruct)(void *e); // destruct object | ||
36 | |||
37 | void *max_size; // keep the current maximal size | ||
38 | int (*max_size_update)(void *max_size, const void *e); // update the max_size | ||
39 | int (*max_size_destruct)(void *max_size); // destruct the size-object | ||
40 | |||
41 | int (*add_item_mem)(void *e, void *s, uint32_t item); | ||
42 | int (*add_item_file)(FILE *fd, void *e, void *s, uint32_t item); | ||
43 | |||
44 | int (*pre_write)(void *e, void *s); // do whatever you want, just before the entry is wrtiiten | ||
45 | }; | ||
46 | |||
47 | struct array_buffer* new_array_buffer( int (*cmp)(const void *a, const void *b), | ||
48 | int (*serialize)(FILE *fd, const void *e), | ||
49 | int (*unserialize)(void **e, FILE *fd), | ||
50 | uint32_t (*get_length)(const void *size), | ||
51 | int (*write)(FILE *fd, void *e, const void *size), | ||
52 | int (*destruct)(void *e), | ||
53 | char* file_name, | ||
54 | void* max_size, | ||
55 | int (*max_size_update)(void *max_size, const void *e), | ||
56 | int (*max_size_destruct)(void *max_size), | ||
57 | int (*add_item_mem)(void *e, void *s, uint32_t item), | ||
58 | int (*add_item_file)(FILE *fd, void *e, void *s, uint32_t item), | ||
59 | int (*pre_write)(void *e, void *s) | ||
60 | ); | ||
61 | /* This makes a new array_buffer | ||
62 | * - cmp() is the compare function used to sort: after sort cmp(item[i], item[i+1])<=0 | ||
63 | * - serialize() should put the entry into the file at the current location, return 0 on success | ||
64 | * - unserialize() should read an entry from file and return the entry in memory. | ||
65 | * return 0 on success, 1 on malloc() failures, 2 on fread() errors, | ||
66 | * anything else on other errors | ||
67 | * - get_length() calculates the length of the entry as it will be written by write() | ||
68 | * - write() should write the entry to file in it's final format | ||
69 | * - destruct() should free all memory assigned to e (including e itself) | ||
70 | * | ||
71 | * - file_name should contain a filename that can be used as extra storage if needed | ||
72 | * if malloc()'s fail, the array is automaticaly converted to file-mode | ||
73 | * and array_buffer retries the operation. | ||
74 | * by not setting file_name=NULL malloc() failures will result in call | ||
75 | * failures | ||
76 | * | ||
77 | * - max_size may be an object to record the maximal size \ | ||
78 | * - max_size_update() will be called on each add() to update the max_size-structure | may be NULL | ||
79 | * - max_size_destroy() should destroy the given max_size object / | ||
80 | * | ||
81 | * - add_item_mem() add item to the entry when it is in memory (may be NULL) | ||
82 | * - add_item_file() add item to the serialized entry at the current file position. | ||
83 | * the entry itself is also given in e for convenience. | ||
84 | * If the add cannot be done in-place the function should | ||
85 | * - invalidate the serialized entry | ||
86 | * - return ERR_NO_INPLACE_UPDATE | ||
87 | * The add will be done in memory and re-added to the end of the | ||
88 | * array (mey be NULL) | ||
89 | * both functions must update the s-structure to reflect the maximal entry | ||
90 | * | ||
91 | * - pre_write() is called right before the entry is written to disk in the write() call (may be NULL) | ||
92 | * | ||
93 | * It returns that buffer on succes, NULL otherwise | ||
94 | * NULL indicates a memory-allocation failure | ||
95 | */ | ||
96 | |||
97 | int array_buffer_destruct(struct array_buffer *b, const int free_file_name); | ||
98 | /* Destructs the buffer: | ||
99 | * - destructs all containing elements using the supplied destruct() function | ||
100 | * - free()'s all allocations | ||
101 | * - optionaly free()'s the file_name | ||
102 | * - free()'s b itself | ||
103 | */ | ||
104 | |||
105 | int array_buffer_switch_to_file(struct array_buffer *b); | ||
106 | /* Asks the buffer to switch to file mode | ||
107 | * returns 0 on success, 1 on failure | ||
108 | */ | ||
109 | |||
110 | inline uint32_t array_buffer_get_next_index(struct array_buffer *b); | ||
111 | /* Returns the index that will be given to the next added entry | ||
112 | */ | ||
113 | |||
114 | int array_buffer_add(struct array_buffer *b, void *e, uint32_t *index); | ||
115 | /* Adds entry e to the buffer. | ||
116 | * If index!=NULL *index will contain a unique number for the entry | ||
117 | * | ||
118 | * Returns 0 on succes, 1 otherwise | ||
119 | * Once an entry is added, the caller should not use the pointer (e) anymore, | ||
120 | * since array_buffer may swap the entry out to file | ||
121 | */ | ||
122 | |||
123 | int array_buffer_entry_update(struct array_buffer *b, const uint32_t index, uint32_t item); | ||
124 | /* Updates entry index with item, either in memory or in file, depending on the current | ||
125 | * state of the array | ||
126 | * Returns ERR_NONE on success | ||
127 | * ERR_MALLOC on malloc() failure | ||
128 | * ERR_FILE on fread(), fwrite(), fseek() problems | ||
129 | */ | ||
130 | |||
131 | int array_buffer_find_entry(struct array_buffer *b, const void *needle, uint32_t *index); | ||
132 | /* This looks for an entry that is equal to needle (i.e. that cmp(e, needle) returns 0) | ||
133 | * Returns ERR_NONE on success (the entry is found) | ||
134 | * ERR_NOTFOUNF when needle was not found, | ||
135 | * ERR_MALLOC on malloc() failure | ||
136 | * ERR_FILE on fread(), fwrite() of other file() failures | ||
137 | */ | ||
138 | |||
139 | int array_buffer_sort(struct array_buffer *b); | ||
140 | /* | ||
141 | */ | ||
142 | |||
143 | uint32_t array_buffer_get_offset(struct array_buffer *b, const uint32_t index); | ||
144 | /* Returns the offset of item[index] when it would be written by the | ||
145 | * array_buffer_write() call. | ||
146 | * Useful to get offsets after sorting! | ||
147 | */ | ||
148 | |||
149 | uint32_t array_buffer_get_length(struct array_buffer *b); | ||
150 | /* Returns the total number of bytes array_buffer_write() | ||
151 | * would write to the file | ||
152 | */ | ||
153 | |||
154 | int array_buffer_write(FILE *fd, struct array_buffer *b); | ||
155 | /* Iterate over each element and write it to file | ||
156 | * returns 0 on success, 1 on failure | ||
157 | */ | ||
158 | |||
159 | #endif | ||