#ifndef ALLOC_H #define ALLOC_H struct alloc_state; struct tree; struct commit; struct tag; struct repository; void *alloc_blob_node(struct repository *r); void *alloc_tree_node(struct repository *r); void init_commit_node(struct commit *c); void *alloc_commit_node(struct repository *r); void *alloc_tag_node(struct repository *r); void *alloc_object_node(struct repository *r); struct alloc_state *allocate_alloc_state(void); void clear_alloc_state(struct alloc_state *s); #define alloc_nr(x) (((x)+16)*3/2) /** * Dynamically growing an array using realloc() is error prone and boring. * * Define your array with: * * - a pointer (`item`) that points at the array, initialized to `NULL` * (although please name the variable based on its contents, not on its * type); * * - an integer variable (`alloc`) that keeps track of how big the current * allocation is, initialized to `0`; * * - another integer variable (`nr`) to keep track of how many elements the * array currently has, initialized to `0`. * * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n, * alloc)`. This ensures that the array can hold at least `n` elements by * calling `realloc(3)` and adjusting `alloc` variable. * * ------------ * sometype *item; * size_t nr; * size_t alloc * * for (i = 0; i < nr; i++) * if (we like item[i] already) * return; * * // we did not like any existing one, so add one * ALLOC_GROW(item, nr + 1, alloc); * item[nr++] = value you like; * ------------ * * You are responsible for updating the `nr` variable. * * If you need to specify the number of elements to allocate explicitly * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`. * * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some * added niceties. * * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'. */ #define ALLOC_GROW(x, nr, alloc) \ do { \ if ((nr) > alloc) { \ if (alloc_nr(alloc) < (nr)) \ alloc = (nr); \ else \ alloc = alloc_nr(alloc); \ REALLOC_ARRAY(x, alloc); \ } \ } while (0) /* * Similar to ALLOC_GROW but handles updating of the nr value and * zeroing the bytes of the newly-grown array elements. * * DO NOT USE any expression with side-effect for any of the * arguments. */ #define ALLOC_GROW_BY(x, nr, increase, alloc) \ do { \ if (increase) { \ size_t new_nr = nr + (increase); \ if (new_nr < nr) \ BUG("negative growth in ALLOC_GROW_BY"); \ ALLOC_GROW(x, new_nr, alloc); \ memset((x) + nr, 0, sizeof(*(x)) * (increase)); \ nr = new_nr; \ } \ } while (0) #endif