xref: /linux/fs/bcachefs/darray.h (revision f6154d8babbb8a98f0d3ea325aafae2e33bfd8be)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHEFS_DARRAY_H
3 #define _BCACHEFS_DARRAY_H
4 
5 /*
6  * Dynamic arrays:
7  *
8  * Inspired by CCAN's darray
9  */
10 
11 #include "util.h"
12 #include <linux/slab.h>
13 
14 #define DARRAY(type)							\
15 struct {								\
16 	size_t nr, size;						\
17 	type *data;							\
18 }
19 
20 typedef DARRAY(void) darray_void;
21 
22 static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more, gfp_t gfp)
23 {
24 	if (d->nr + more > d->size) {
25 		size_t new_size = roundup_pow_of_two(d->nr + more);
26 		void *data = krealloc_array(d->data, new_size, t_size, gfp);
27 
28 		if (!data)
29 			return -ENOMEM;
30 
31 		d->data	= data;
32 		d->size = new_size;
33 	}
34 
35 	return 0;
36 }
37 
38 #define darray_make_room_gfp(_d, _more, _gfp)				\
39 	__darray_make_room((darray_void *) (_d), sizeof((_d)->data[0]), (_more), _gfp)
40 
41 #define darray_make_room(_d, _more)					\
42 	darray_make_room_gfp(_d, _more, GFP_KERNEL)
43 
44 #define darray_top(_d)		((_d).data[(_d).nr])
45 
46 #define darray_push_gfp(_d, _item, _gfp)				\
47 ({									\
48 	int _ret = darray_make_room_gfp((_d), 1, _gfp);			\
49 									\
50 	if (!_ret)							\
51 		(_d)->data[(_d)->nr++] = (_item);			\
52 	_ret;								\
53 })
54 
55 #define darray_push(_d, _item)	darray_push_gfp(_d, _item, GFP_KERNEL)
56 
57 #define darray_pop(_d)		((_d)->data[--(_d)->nr])
58 
59 #define darray_first(_d)	((_d).data[0])
60 #define darray_last(_d)		((_d).data[(_d).nr - 1])
61 
62 #define darray_insert_item(_d, pos, _item)				\
63 ({									\
64 	size_t _pos = (pos);						\
65 	int _ret = darray_make_room((_d), 1);				\
66 									\
67 	if (!_ret)							\
68 		array_insert_item((_d)->data, (_d)->nr, _pos, (_item));	\
69 	_ret;								\
70 })
71 
72 #define darray_remove_item(_d, _pos)					\
73 	array_remove_item((_d)->data, (_d)->nr, (_pos) - (_d)->data)
74 
75 #define darray_for_each(_d, _i)						\
76 	for (_i = (_d).data; _i < (_d).data + (_d).nr; _i++)
77 
78 #define darray_for_each_reverse(_d, _i)					\
79 	for (_i = (_d).data + (_d).nr - 1; _i >= (_d).data; --_i)
80 
81 #define darray_init(_d)							\
82 do {									\
83 	(_d)->data = NULL;						\
84 	(_d)->nr = (_d)->size = 0;					\
85 } while (0)
86 
87 #define darray_exit(_d)							\
88 do {									\
89 	kfree((_d)->data);						\
90 	darray_init(_d);						\
91 } while (0)
92 
93 #endif /* _BCACHEFS_DARRAY_H */
94