96 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
| #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
 |