]> git.ipfire.org Git - thirdparty/git.git/blob - alloc.h
hash-ll.h: split out of hash.h to remove dependency on repository.h
[thirdparty/git.git] / alloc.h
1 #ifndef ALLOC_H
2 #define ALLOC_H
3
4 struct alloc_state;
5 struct tree;
6 struct commit;
7 struct tag;
8 struct repository;
9
10 void *alloc_blob_node(struct repository *r);
11 void *alloc_tree_node(struct repository *r);
12 void init_commit_node(struct commit *c);
13 void *alloc_commit_node(struct repository *r);
14 void *alloc_tag_node(struct repository *r);
15 void *alloc_object_node(struct repository *r);
16
17 struct alloc_state *allocate_alloc_state(void);
18 void clear_alloc_state(struct alloc_state *s);
19
20 #define alloc_nr(x) (((x)+16)*3/2)
21
22 /**
23 * Dynamically growing an array using realloc() is error prone and boring.
24 *
25 * Define your array with:
26 *
27 * - a pointer (`item`) that points at the array, initialized to `NULL`
28 * (although please name the variable based on its contents, not on its
29 * type);
30 *
31 * - an integer variable (`alloc`) that keeps track of how big the current
32 * allocation is, initialized to `0`;
33 *
34 * - another integer variable (`nr`) to keep track of how many elements the
35 * array currently has, initialized to `0`.
36 *
37 * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
38 * alloc)`. This ensures that the array can hold at least `n` elements by
39 * calling `realloc(3)` and adjusting `alloc` variable.
40 *
41 * ------------
42 * sometype *item;
43 * size_t nr;
44 * size_t alloc
45 *
46 * for (i = 0; i < nr; i++)
47 * if (we like item[i] already)
48 * return;
49 *
50 * // we did not like any existing one, so add one
51 * ALLOC_GROW(item, nr + 1, alloc);
52 * item[nr++] = value you like;
53 * ------------
54 *
55 * You are responsible for updating the `nr` variable.
56 *
57 * If you need to specify the number of elements to allocate explicitly
58 * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`.
59 *
60 * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some
61 * added niceties.
62 *
63 * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
64 */
65 #define ALLOC_GROW(x, nr, alloc) \
66 do { \
67 if ((nr) > alloc) { \
68 if (alloc_nr(alloc) < (nr)) \
69 alloc = (nr); \
70 else \
71 alloc = alloc_nr(alloc); \
72 REALLOC_ARRAY(x, alloc); \
73 } \
74 } while (0)
75
76 /*
77 * Similar to ALLOC_GROW but handles updating of the nr value and
78 * zeroing the bytes of the newly-grown array elements.
79 *
80 * DO NOT USE any expression with side-effect for any of the
81 * arguments.
82 */
83 #define ALLOC_GROW_BY(x, nr, increase, alloc) \
84 do { \
85 if (increase) { \
86 size_t new_nr = nr + (increase); \
87 if (new_nr < nr) \
88 BUG("negative growth in ALLOC_GROW_BY"); \
89 ALLOC_GROW(x, new_nr, alloc); \
90 memset((x) + nr, 0, sizeof(*(x)) * (increase)); \
91 nr = new_nr; \
92 } \
93 } while (0)
94
95 #endif