]>
Commit | Line | Data |
---|---|---|
14ba97f8 SB |
1 | #ifndef ALLOC_H |
2 | #define ALLOC_H | |
3 | ||
ef3ca954 | 4 | struct alloc_state; |
14ba97f8 SB |
5 | struct tree; |
6 | struct commit; | |
7 | struct tag; | |
ef3ca954 | 8 | struct repository; |
14ba97f8 SB |
9 | |
10 | void *alloc_blob_node(struct repository *r); | |
11 | void *alloc_tree_node(struct repository *r); | |
6da43d93 | 12 | void init_commit_node(struct commit *c); |
14ba97f8 SB |
13 | void *alloc_commit_node(struct repository *r); |
14 | void *alloc_tag_node(struct repository *r); | |
15 | void *alloc_object_node(struct repository *r); | |
14ba97f8 | 16 | |
17313107 | 17 | struct alloc_state *allocate_alloc_state(void); |
14ba97f8 SB |
18 | void clear_alloc_state(struct alloc_state *s); |
19 | ||
36bf1958 EN |
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 | ||
14ba97f8 | 95 | #endif |