1 #ifndef R_SPACES_H
2 #define R_SPACES_H
3 
4 #define R_SPACES_MAX 512
5 
6 #include "r_util.h"
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 /*
13  * RSpaces represents a set of Spaces.
14  * A Space is used to group similar objects and it can have a name. Name
15  * "*"/""/NULL is reserved to indicate "all spaces".
16  *
17  * You can have groups of "meta" (e.g. bin meta, format meta, etc.), groups of
18  * zign info, groups of flags, etc.
19  *
20  * It is possible to hook into the RSpaces functions by using REvent.
21  * R_SPACE_EVENT_COUNT: called when you need to count how many elements there are in a given RSpace
22  * R_SPACE_EVENT_RENAME: called when renaming a RSpace with an oldname to a newname
23  * R_SPACE_EVENT_UNSET: called when deleting a RSpace with a given name
24  */
25 
26 typedef struct r_space_t {
27 	char *name;
28 	RBNode rb;
29 } RSpace;
30 
31 typedef enum {
32 	R_SPACE_EVENT_COUNT = 1,
33 	R_SPACE_EVENT_RENAME,
34 	R_SPACE_EVENT_UNSET,
35 } RSpaceEventType;
36 
37 typedef struct r_space_event_t {
38 	union {
39 		struct {
40 			const RSpace *space;
41 		} count;
42 		struct {
43 			const RSpace *space;
44 		} unset;
45 		struct {
46 			const RSpace *space;
47 			const char *oldname;
48 			const char *newname;
49 		} rename;
50 	} data;
51 	int res;
52 } RSpaceEvent;
53 
54 typedef struct r_spaces_t {
55 	const char *name;
56 	RSpace *current;
57 	RBTree spaces;
58 	RList *spacestack;
59 	REvent *event;
60 } RSpaces;
61 
62 // Create a new RSpaces with the given name
63 R_API RSpaces *r_spaces_new(const char *name);
64 // Initialize an existing RSpaces with the given name
65 R_API bool r_spaces_init(RSpaces *sp, const char *name);
66 // Finalize an existing RSpaces
67 R_API void r_spaces_fini(RSpaces *sp);
68 // Finalize and free an existing RSpaces
69 R_API void r_spaces_free(RSpaces *sp);
70 // Delete all spaces
71 R_API void r_spaces_purge(RSpaces *sp);
72 // Get the RSpace with the given name
73 R_API RSpace *r_spaces_get(RSpaces *sp, const char *name);
74 // Add a new RSpace if one does not already exist, otherwise return the existing one
75 R_API RSpace *r_spaces_add(RSpaces *sp, const char *name);
76 // Add and select a new RSpace if one does not already exist, otherwise return and select the existing one
77 R_API RSpace *r_spaces_set(RSpaces *sp, const char *name);
78 // Remove the RSpace with the given name or all of them if name is NULL
79 R_API bool r_spaces_unset(RSpaces *sp, const char *name);
80 // Change the name of RSpace with oname to nname
81 R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname);
82 // Count the elements that belong to the RSpace with the given name
83 R_API int r_spaces_count(RSpaces *sp, const char *name);
84 // Add/Select the RSpace with the given name and save the current one in the history
85 R_API bool r_spaces_push(RSpaces *sp, const char *name);
86 // Select the RSpace that was set before the current one
87 R_API bool r_spaces_pop(RSpaces *sp);
88 
r_spaces_current(RSpaces * sp)89 static inline RSpace *r_spaces_current(RSpaces *sp) {
90 	return sp->current;
91 }
92 
r_spaces_current_name(RSpaces * sp)93 static inline const char *r_spaces_current_name(RSpaces *sp) {
94 	return sp->current? sp->current->name: "*";
95 }
96 
r_spaces_is_empty(RSpaces * sp)97 static inline bool r_spaces_is_empty(RSpaces *sp) {
98 	RBIter it = r_rbtree_first (sp->spaces);
99 	return it.len == 0;
100 }
101 
102 typedef RBIter RSpaceIter;
103 #define r_spaces_foreach(sp, it, s) \
104 	r_rbtree_foreach ((sp)->spaces, (it), (s), RSpace, rb)
105 
106 #ifdef __cplusplus
107 }
108 #endif
109 
110 #endif //  R_SPACES_H
111