xref: /linux-6.15/fs/bcachefs/darray.h (revision 8dabb19f)
191d961baSKent Overstreet /* SPDX-License-Identifier: GPL-2.0 */
291d961baSKent Overstreet #ifndef _BCACHEFS_DARRAY_H
391d961baSKent Overstreet #define _BCACHEFS_DARRAY_H
491d961baSKent Overstreet 
591d961baSKent Overstreet /*
691d961baSKent Overstreet  * Dynamic arrays:
791d961baSKent Overstreet  *
891d961baSKent Overstreet  * Inspired by CCAN's darray
991d961baSKent Overstreet  */
1091d961baSKent Overstreet 
1191d961baSKent Overstreet #include <linux/slab.h>
1291d961baSKent Overstreet 
13099dc5c2SKent Overstreet #define DARRAY_PREALLOCATED(_type, _nr)					\
1491d961baSKent Overstreet struct {								\
1591d961baSKent Overstreet 	size_t nr, size;						\
16099dc5c2SKent Overstreet 	_type *data;							\
17099dc5c2SKent Overstreet 	_type preallocated[_nr];					\
1891d961baSKent Overstreet }
1991d961baSKent Overstreet 
20099dc5c2SKent Overstreet #define DARRAY(_type) DARRAY_PREALLOCATED(_type, 0)
2191d961baSKent Overstreet 
22099dc5c2SKent Overstreet typedef DARRAY(char)	darray_char;
23806ebf2aSKent Overstreet typedef DARRAY(char *) darray_str;
2473ab9e03SKent Overstreet 
25a803fa55SKent Overstreet int __bch2_darray_resize_noprof(darray_char *, size_t, size_t, gfp_t);
26099dc5c2SKent Overstreet 
27a803fa55SKent Overstreet #define __bch2_darray_resize(...)	alloc_hooks(__bch2_darray_resize_noprof(__VA_ARGS__))
28a803fa55SKent Overstreet 
29a803fa55SKent Overstreet #define __darray_resize(_d, _element_size, _new_size, _gfp)		\
30a803fa55SKent Overstreet 	(unlikely((_new_size) > (_d)->size)				\
31a803fa55SKent Overstreet 	 ? __bch2_darray_resize((_d), (_element_size), (_new_size), (_gfp))\
32a803fa55SKent Overstreet 	 : 0)
3391d961baSKent Overstreet 
3473ab9e03SKent Overstreet #define darray_resize_gfp(_d, _new_size, _gfp)				\
35a803fa55SKent Overstreet 	__darray_resize((darray_char *) (_d), sizeof((_d)->data[0]), (_new_size), _gfp)
3673ab9e03SKent Overstreet 
3773ab9e03SKent Overstreet #define darray_resize(_d, _new_size)					\
3873ab9e03SKent Overstreet 	darray_resize_gfp(_d, _new_size, GFP_KERNEL)
3973ab9e03SKent Overstreet 
409edbcc72SKent Overstreet #define darray_make_room_gfp(_d, _more, _gfp)				\
41a803fa55SKent Overstreet 	darray_resize_gfp((_d), (_d)->nr + (_more), _gfp)
429edbcc72SKent Overstreet 
4391d961baSKent Overstreet #define darray_make_room(_d, _more)					\
449edbcc72SKent Overstreet 	darray_make_room_gfp(_d, _more, GFP_KERNEL)
4591d961baSKent Overstreet 
4673ab9e03SKent Overstreet #define darray_room(_d)		((_d).size - (_d).nr)
4773ab9e03SKent Overstreet 
4891d961baSKent Overstreet #define darray_top(_d)		((_d).data[(_d).nr])
4991d961baSKent Overstreet 
509edbcc72SKent Overstreet #define darray_push_gfp(_d, _item, _gfp)				\
5191d961baSKent Overstreet ({									\
529edbcc72SKent Overstreet 	int _ret = darray_make_room_gfp((_d), 1, _gfp);			\
5391d961baSKent Overstreet 									\
5491d961baSKent Overstreet 	if (!_ret)							\
5591d961baSKent Overstreet 		(_d)->data[(_d)->nr++] = (_item);			\
5691d961baSKent Overstreet 	_ret;								\
5791d961baSKent Overstreet })
5891d961baSKent Overstreet 
599edbcc72SKent Overstreet #define darray_push(_d, _item)	darray_push_gfp(_d, _item, GFP_KERNEL)
609edbcc72SKent Overstreet 
61c42b57c4SKent Overstreet #define darray_pop(_d)		((_d)->data[--(_d)->nr])
62c42b57c4SKent Overstreet 
63c42b57c4SKent Overstreet #define darray_first(_d)	((_d).data[0])
64c42b57c4SKent Overstreet #define darray_last(_d)		((_d).data[(_d).nr - 1])
65c42b57c4SKent Overstreet 
66bf5a261cSKent Overstreet #define darray_insert_item(_d, pos, _item)				\
6791d961baSKent Overstreet ({									\
68bf5a261cSKent Overstreet 	size_t _pos = (pos);						\
6991d961baSKent Overstreet 	int _ret = darray_make_room((_d), 1);				\
7091d961baSKent Overstreet 									\
7191d961baSKent Overstreet 	if (!_ret)							\
72bf5a261cSKent Overstreet 		array_insert_item((_d)->data, (_d)->nr, _pos, (_item));	\
7391d961baSKent Overstreet 	_ret;								\
7491d961baSKent Overstreet })
7591d961baSKent Overstreet 
76d4c8bb69SKent Overstreet #define darray_remove_item(_d, _pos)					\
77d4c8bb69SKent Overstreet 	array_remove_item((_d)->data, (_d)->nr, (_pos) - (_d)->data)
78d4c8bb69SKent Overstreet 
79defd9e39SKent Overstreet #define __darray_for_each(_d, _i)						\
80defd9e39SKent Overstreet 	for ((_i) = (_d).data; _i < (_d).data + (_d).nr; _i++)
81defd9e39SKent Overstreet 
8291d961baSKent Overstreet #define darray_for_each(_d, _i)						\
83defd9e39SKent Overstreet 	for (typeof(&(_d).data[0]) _i = (_d).data; _i < (_d).data + (_d).nr; _i++)
8491d961baSKent Overstreet 
85d4c8bb69SKent Overstreet #define darray_for_each_reverse(_d, _i)					\
86*8dabb19fSKent Overstreet 	for (typeof(&(_d).data[0]) _i = (_d).data + (_d).nr - 1; _i >= (_d).data && (_d).nr; --_i)
87d4c8bb69SKent Overstreet 
8891d961baSKent Overstreet #define darray_init(_d)							\
8991d961baSKent Overstreet do {									\
90099dc5c2SKent Overstreet 	(_d)->nr = 0;							\
91099dc5c2SKent Overstreet 	(_d)->size = ARRAY_SIZE((_d)->preallocated);			\
92099dc5c2SKent Overstreet 	(_d)->data = (_d)->size ? (_d)->preallocated : NULL;		\
9391d961baSKent Overstreet } while (0)
9491d961baSKent Overstreet 
9591d961baSKent Overstreet #define darray_exit(_d)							\
9691d961baSKent Overstreet do {									\
97099dc5c2SKent Overstreet 	if (!ARRAY_SIZE((_d)->preallocated) ||				\
98099dc5c2SKent Overstreet 	    (_d)->data != (_d)->preallocated)				\
99a58a6a58SKent Overstreet 		kvfree((_d)->data);					\
10091d961baSKent Overstreet 	darray_init(_d);						\
10191d961baSKent Overstreet } while (0)
10291d961baSKent Overstreet 
10391d961baSKent Overstreet #endif /* _BCACHEFS_DARRAY_H */
104