1 #ifndef __ARRAY_BUFFER_H__
2 #define __ARRAY_BUFFER_H__
9 uint32_t count
; // how much items doe we have?
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
19 uint32_t *sort
; // In what order should we put the entries on disk?
21 char* file_name
; // filename
22 FILE *fd
; // file where entries are being kept. (NULL if in mem)
24 int (*cmp
)(const void *a
, const void *b
); // compare a to b, should return:
29 int (*serialize
)(FILE *fd
, const void *e
); // serialize e into fd
30 int (*unserialize
)(void **e
, FILE *fd
); // unserialize the entry in fd
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
35 int (*destruct
)(void *e
); // destruct object
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
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
);
44 int (*pre_write
)(void *e
, void *s
); // do whatever you want, just before the entry is wrtiiten
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
),
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
)
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)
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
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 /
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
89 * both functions must update the s-structure to reflect the maximal entry
91 * - pre_write() is called right before the entry is written to disk in the write() call (may be NULL)
93 * It returns that buffer on succes, NULL otherwise
94 * NULL indicates a memory-allocation failure
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
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
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
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
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
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
126 * Returns ERR_NONE on success
127 * ERR_MALLOC on malloc() failure
128 * ERR_FILE on fread(), fwrite(), fseek() problems
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
139 int array_buffer_sort(struct array_buffer
*b
);
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!
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
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