libamxc  1.10.3
C Generic Data Containers
Set

The Ambiorix set is an abstract data type that can store unique values. More...

Data Structures

struct  _flag
 The flag structure. More...
 
struct  _set
 The set structure. More...
 

Typedefs

typedef struct _flag amxc_flag_t
 The flag structure. More...
 

Functions

int amxc_set_new (amxc_set_t **set, bool counted)
 Allocates a set. More...
 
void amxc_set_delete (amxc_set_t **set)
 Frees a set. More...
 
int amxc_set_init (amxc_set_t *const set, bool counted)
 Initializes a set. More...
 
void amxc_set_clean (amxc_set_t *const set)
 Cleans a set. More...
 
amxc_set_tamxc_set_copy (const amxc_set_t *const set)
 Copies a set. More...
 
void amxc_set_reset (amxc_set_t *set)
 Reset or empty a set, i.e. clear all flags. More...
 
int amxc_set_parse (amxc_set_t *set, const char *str)
 Parses a space-separated string of flags and adds them to the set. More...
 
char * amxc_set_to_string (const amxc_set_t *const set)
 Converts a set to a space-separated string of flags. More...
 
char * amxc_set_to_string_sep (const amxc_set_t *const set, const char *sep)
 Converts a set to a separated string of flags. More...
 
void amxc_set_add_flag (amxc_set_t *set, const char *flag)
 Adds a flag to a set, or increases the flag counter. More...
 
void amxc_set_remove_flag (amxc_set_t *set, const char *flag)
 Removes a flag from a set or decreases the flag counter. More...
 
bool amxc_set_has_flag (const amxc_set_t *const set, const char *flag)
 Check if a set contains a flag. More...
 
uint32_t amxc_set_get_count (const amxc_set_t *const set, const char *flag)
 Get a flag counter. More...
 
void amxc_set_union (amxc_set_t *const set, const amxc_set_t *const operand)
 Joins two sets. More...
 
void amxc_set_intersect (amxc_set_t *const set, const amxc_set_t *const operand)
 Intersect a set with another set. More...
 
void amxc_set_subtract (amxc_set_t *const set, const amxc_set_t *const operand)
 Subtract a set from another set. More...
 
bool amxc_set_is_equal (const amxc_set_t *const set1, const amxc_set_t *const set2)
 Compare two sets. More...
 
void amxc_set_alert_cb (amxc_set_t *set, amxc_set_alert_t handler, void *priv)
 Install a set alert callback function. More...
 
void amxc_set_symmetric_difference (amxc_set_t *const set, const amxc_set_t *const operand)
 Calculates the symmetric difference of two sets. More...
 

Detailed Description

The Ambiorix set is an abstract data type that can store unique values.

A set is an abstract data type that can store unique values, without any particular order. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set.

Typedef Documentation

◆ amxc_flag_t

typedef struct _flag amxc_flag_t

The flag structure.

Flags can be added to a set.

Function Documentation

◆ amxc_set_add_flag()

void amxc_set_add_flag ( amxc_set_t set,
const char *  flag 
)

Adds a flag to a set, or increases the flag counter.

Adds a flag to a set if it does not contain it already. If the set already contains the flag, increase its counter if the flag set is a counted set or do nothing at all for normal flag sets.

Parameters
setThe flag set on which a flag needs to be added.
flagThe flag to add.

Definition at line 305 of file amxc_set.c.

305  {
306  when_null(set, exit);
307  when_str_empty(flag, exit);
308 
309  amxc_set_flag_add(set, flag, 0, 1);
310 
311 exit:
312  return;
313 }
#define when_null(x, l)
Definition: amxc_macros.h:126
#define when_str_empty(x, l)
Definition: amxc_macros.h:146
static void amxc_set_flag_add(amxc_set_t *set, const char *flag, int flaglen, int count)
Definition: amxc_set.c:84

◆ amxc_set_alert_cb()

void amxc_set_alert_cb ( amxc_set_t set,
amxc_set_alert_t  handler,
void *  priv 
)

Install a set alert callback function.

For normal sets, this handler is called every time a flag is added or removed from the set.

For counted sets, this handler is called only whenever a flag is really added to or removed from the flag set, i.e. not when setting or clearing a flag only causes a flag counter to be incremented or decremented.

Parameters
setThe set on which an alert handler needs to be installed.
handlerThe callback function to be called whenever a flag is set or cleared.
privA void pointer to be passed to the callback function.

Definition at line 453 of file amxc_set.c.

453  {
454  when_null(set, exit);
455 
456  set->alert_handler = handler;
457  set->priv = priv;
458 
459 exit:
460  return;
461 }
amxc_set_alert_t alert_handler
Definition: amxc_set.h:131
void * priv
Definition: amxc_set.h:133

◆ amxc_set_clean()

void amxc_set_clean ( amxc_set_t *const  set)

Cleans a set.

clean-up a set, which was previously initialized with amxc_set_init.

Parameters
seta pointer to an amxc_set_t structure

Definition at line 177 of file amxc_set.c.

177  {
178  when_null(set, exit);
179 
181  set->count = 0;
182 
183 exit:
184  return;
185 }
static void amxc_set_flag_free(amxc_llist_it_t *it)
Definition: amxc_set.c:66
void amxc_llist_clean(amxc_llist_t *const llist, amxc_llist_it_delete_t func)
Removes all items from the linked list.
Definition: amxc_llist.c:124
int count
Definition: amxc_set.h:135
amxc_llist_t list
Definition: amxc_set.h:130

◆ amxc_set_copy()

amxc_set_t* amxc_set_copy ( const amxc_set_t *const  set)

Copies a set.

Allocates a new set and copies the flags of the given set into this new set. The set alert handler and private data are not copied.

Note
The allocated memory must be freed when not used anymore, use amxc_set_delete to free the memory.
Parameters
seta pointer to an amxc_set_t structure
Returns
A pointer to the newly allocated amxc_set_t structure if the copy succeeded, NULL otherwise.

Definition at line 187 of file amxc_set.c.

187  {
188  amxc_set_t* copy = NULL;
189 
190  when_null(set, exit);
191  when_failed(amxc_set_new(&copy, set->counted), exit);
192 
193  amxc_set_union(copy, set);
194 
195 exit:
196  return copy;
197 }
#define when_failed(x, l)
Definition: amxc_macros.h:142
int amxc_set_new(amxc_set_t **set, bool counted)
Allocates a set.
Definition: amxc_set.c:138
void amxc_set_union(amxc_set_t *const set, const amxc_set_t *const operand)
Joins two sets.
Definition: amxc_set.c:365
The set structure.
Definition: amxc_set.h:129
bool counted
Definition: amxc_set.h:134

◆ amxc_set_delete()

void amxc_set_delete ( amxc_set_t **  set)

Frees a set.

Releases any allocated memory for the flag set.

Parameters
setThe set to destroy. When this function returns, the pointer is set to NULL.

Definition at line 151 of file amxc_set.c.

151  {
152  when_null(set, exit);
153 
154  amxc_set_clean(*set);
155  free(*set);
156  *set = NULL;
157 
158 exit:
159  return;
160 }
void amxc_set_clean(amxc_set_t *const set)
Cleans a set.
Definition: amxc_set.c:177

◆ amxc_set_get_count()

uint32_t amxc_set_get_count ( const amxc_set_t *const  set,
const char *  flag 
)

Get a flag counter.

Get the counter of a specific flag if flag is non-NULL or the global flag set counter if flag is NULL. The global counter is the sum of all flag counters. For counted sets, the counter of a flag is the number of times the flag was set. For normal flag sets, the counter equals 1 if the flag is set.

Parameters
setThe set for which a counter needs to be returned. NULL is considered to be the empty flag set.
flagThe flag to count. If it equals NULL, the global flag set counter is returned.
Returns
A flag counter or the flag set's global counter.

Definition at line 349 of file amxc_set.c.

349  {
350  uint32_t retval = 0;
351 
352  when_null(set, exit);
353 
354  if((flag != NULL) && (*flag != 0)) {
355  amxc_flag_t* f = amxc_set_flag_find(set, flag);
356  retval = f != NULL ? f->count : 0;
357  } else {
358  return set->count;
359  }
360 
361 exit:
362  return retval;
363 }
static amxc_flag_t * amxc_set_flag_find(const amxc_set_t *const set, const char *flag)
Definition: amxc_set.c:72
The flag structure.
Definition: amxc_set.h:118
uint32_t count
Definition: amxc_set.h:121

◆ amxc_set_has_flag()

bool amxc_set_has_flag ( const amxc_set_t *const  set,
const char *  flag 
)

Check if a set contains a flag.

Parameters
setThe set on which the flag needs to be checked. NULL is considered to be the empty flag set.
flagThe flag to check.
Returns
True if and only if the flag is set.

Definition at line 337 of file amxc_set.c.

337  {
338  bool retval = false;
339 
340  when_null(set, exit);
341  when_str_empty(flag, exit);
342 
343  retval = amxc_set_flag_find(set, flag) ? true : false;
344 
345 exit:
346  return retval;
347 }

◆ amxc_set_init()

int amxc_set_init ( amxc_set_t *const  set,
bool  counted 
)

Initializes a set.

Initializes a set that is declared on the stack. When the set is not needed anymore use amxc_set_clean to clean it up.

Parameters
seta pointer to an amxc_set_t structure
countedIf set to true, the initialized set will keep a counter for each flag. Each time a specific flag is set, the counter is incremented and when the flag is cleared, the counter is decremented. Only when the counter reaches zero, the flag is really removed from the flag set. If set to false, the flag set will have default behaviour, i.e. when clearing a flag, it is removed immediately no matter how many times it has been set.
Returns
-1 if an error occured. 0 on success

Definition at line 162 of file amxc_set.c.

162  {
163  int retval = -1;
164 
165  when_null(set, exit);
166  amxc_llist_init(&set->list);
167  set->alert_handler = NULL;
168  set->counted = counted;
169  set->count = 0;
170  set->priv = NULL;
171  retval = 0;
172 
173 exit:
174  return retval;
175 }
int amxc_llist_init(amxc_llist_t *const llist)
Initializes a linked list.
Definition: amxc_llist.c:111

◆ amxc_set_intersect()

void amxc_set_intersect ( amxc_set_t *const  set,
const amxc_set_t *const  operand 
)

Intersect a set with another set.

All flags that are set in the set referenced by set, but not in the set referenced by operand, are removed from set. Additionally, for counted sets, the counter of each flag of set will be set to the minimum of itself and the counter of the corresponding flag in operand.

Parameters
setLeft hand operand of the intersect operator, as well as the target to store the result into.
operandRight hand operand of the intersect operator. NULL is considered to be the empty set.

Definition at line 384 of file amxc_set.c.

384  {
385  when_null(set, exit);
386 
387  if(operand == NULL) {
388  amxc_set_reset(set);
389  goto exit;
390  }
391 
392  amxc_llist_for_each(it, &set->list) {
394  amxc_flag_t* fo = amxc_set_flag_find(operand, f->flag);
395 
396  if(fo == NULL) {
397  amxc_set_flag_delete(set, &f->it);
398  } else if(set->counted && (fo->count < f->count)) {
399  set->count += fo->count - f->count;
400  f->count = fo->count;
401  }
402  }
403 
404 exit:
405  return;
406 }
static void amxc_set_flag_delete(amxc_set_t *set, amxc_llist_it_t *it)
Definition: amxc_set.c:128
#define amxc_container_of(addr, type, member)
Calculates the address of the containing structure.
Definition: amxc_common.h:83
#define amxc_llist_for_each(it, list)
Loops over the list from head to tail.
Definition: amxc_llist.h:253
void amxc_set_reset(amxc_set_t *set)
Reset or empty a set, i.e. clear all flags.
Definition: amxc_set.c:199
char * flag
Definition: amxc_set.h:120
amxc_llist_it_t it
Definition: amxc_set.h:119
static amxc_htable_it_t it[2000]

◆ amxc_set_is_equal()

bool amxc_set_is_equal ( const amxc_set_t *const  set1,
const amxc_set_t *const  set2 
)

Compare two sets.

Normal sets are considered to be equal if they contain the exact same set of flags. For counted sets, the flag counters have to match as well in order to be considered as equal.

Parameters
set1Left hand operand of the equals operator. NULL is considered to be the empty set.
set2Right hand operand of the equals operator. NULL is considered to be the empty set.
Returns
True if and only if set1 and set2 are equal.

Definition at line 430 of file amxc_set.c.

431  {
432  if(set1 != NULL) {
433  amxc_llist_iterate(it, &set1->list) {
435  if(amxc_set_get_count(set2, f->flag) != f->count) {
436  return false;
437  }
438  }
439  }
440 
441  if(set2 != NULL) {
442  amxc_llist_iterate(it, &set2->list) {
444  if(amxc_set_get_count(set1, f->flag) != f->count) {
445  return false;
446  }
447  }
448  }
449 
450  return true;
451 }
#define amxc_llist_iterate(it, list)
Loops over the list from head to tail.
Definition: amxc_llist.h:270
uint32_t amxc_set_get_count(const amxc_set_t *const set, const char *flag)
Get a flag counter.
Definition: amxc_set.c:349

◆ amxc_set_new()

int amxc_set_new ( amxc_set_t **  set,
bool  counted 
)

Allocates a set.

Allocates and initializes memory to store a set. This function allocates memory from the heap, if a set is on the stack, it can be initialized using function amxc_set_init

Note
The allocated memory must be freed when not used anymore, use amxc_set_delete to free the memory
Parameters
seta pointer to the location where the pointer to the new set can be stored
countedIf set to true, the created set will keep a counter for each flag. Each time a specific flag is set, the counter is incremented and when the flag is cleared, the counter is decremented. Only when the counter reaches zero, the flag is really removed from the flag set. If set to false, the flag set will have default behaviour, i.e. when clearing a flag, it is removed immediately no matter how many times it has been set.
Returns
-1 if an error occured. 0 on success

Definition at line 138 of file amxc_set.c.

138  {
139  int retval = -1;
140 
141  when_null(set, exit);
142 
143  *set = (amxc_set_t*) calloc(1, sizeof(amxc_set_t));
144  when_null(*set, exit);
145  retval = amxc_set_init(*set, counted);
146 
147 exit:
148  return retval;
149 }
int amxc_set_init(amxc_set_t *const set, bool counted)
Initializes a set.
Definition: amxc_set.c:162

◆ amxc_set_parse()

int amxc_set_parse ( amxc_set_t set,
const char *  str 
)

Parses a space-separated string of flags and adds them to the set.

This function will iterate over the given string, uses space characters as delimiter (uses function isspace). Multiple consecutive spaces are considered as one single space.

When the set is a counted set, a flag can be followed by a : sign and a number, that number is used as the initial count value. If the set is not a counted set, the number is ignored.

The : sign can not be used in flag names.

Parameters
setThe flag set to store the parsed flags into.
strThe string that holds the space separated string of flags.
Returns
0 if the string was parsed successfully, any other value otherwise.

Definition at line 210 of file amxc_set.c.

210  {
211  int retval = -1;
212  amxc_set_t newset;
213 
214  when_null(set, exit);
215  amxc_set_init(&newset, set->counted);
216 
217  if((str != NULL) && (*str != 0)) {
218  const char* strptr = str;
219  char* newstr = NULL;
220  int count = 0;
221  do {
222  if(!((*str == '\0') || (isspace(*str) != 0) || (*str == ':'))) {
223  continue;
224  }
225  if(str > strptr) {
226  if(*str == ':') {
227  count = strtol(str + 1, &newstr, 0);
228  if((*newstr != '\0') && (isspace(*newstr) == 0)) {
229  goto exit_clean;
230  }
231  if(count > 0) {
232  amxc_set_flag_add(&newset, strptr, str - strptr, set->counted ? count : 1);
233  }
234  str = newstr;
235  } else {
236  amxc_set_flag_add(&newset, strptr, str - strptr, 1);
237  }
238  }
239  strptr = str + 1;
240  } while(*str++);
241  }
242  // intersect + union instead of simply overwrite to avoid that unchanged flags are cleared and set again
243  amxc_set_intersect(set, &newset);
244  amxc_set_union(set, &newset);
245  if(set->counted) {
246  set->count = 0;
247  amxc_llist_iterate(it, &set->list) {
249  amxc_flag_t* new_flag = amxc_set_flag_find(&newset, flag->flag);
250  if((flag != NULL) && (new_flag != NULL)) {
251  flag->count = new_flag->count;
252  set->count += flag->count;
253  }
254  }
255  }
256  retval = 0;
257 
258 exit_clean:
259  amxc_set_clean(&newset);
260 exit:
261  return retval;
262 }
void amxc_set_intersect(amxc_set_t *const set, const amxc_set_t *const operand)
Intersect a set with another set.
Definition: amxc_set.c:384

◆ amxc_set_remove_flag()

void amxc_set_remove_flag ( amxc_set_t set,
const char *  flag 
)

Removes a flag from a set or decreases the flag counter.

If the flag set contains the flag, decrease its counter if it is a counted set. If it is a normal flag set, or the flag's counter reaches zero, removes the flag from the set. If the set does not contain the flag, doesn't do anything at all.

Parameters
setThe set on which a flag needs to be removed.
flagThe flag to clear.

Definition at line 315 of file amxc_set.c.

315  {
316  amxc_flag_t* f = NULL;
317 
318  when_null(set, exit);
319  when_str_empty(flag, exit);
320 
321  f = amxc_set_flag_find(set, flag);
322  if(f == NULL) {
323  goto exit;
324  }
325 
326  if(set->counted && (f->count > 1)) {
327  f->count--;
328  set->count--;
329  } else {
330  amxc_set_flag_delete(set, &f->it);
331  }
332 
333 exit:
334  return;
335 }

◆ amxc_set_reset()

void amxc_set_reset ( amxc_set_t set)

Reset or empty a set, i.e. clear all flags.

Parameters
setThe set to reset.

Definition at line 199 of file amxc_set.c.

199  {
200  when_null(set, exit);
201 
202  amxc_llist_for_each(it, &set->list) {
203  amxc_set_flag_delete(set, it);
204  }
205 
206 exit:
207  return;
208 }

◆ amxc_set_subtract()

void amxc_set_subtract ( amxc_set_t *const  set,
const amxc_set_t *const  operand 
)

Subtract a set from another set.

For normal sets, all flags that are set in both the set referenced by set and the set referenced by operand, are removed from set.

For counted sets, the counter of each flag of set will be decremented by the counter of the corresponding flag in operand. If this results in a counter equal to or less than zero, the flag is removed from set.

Parameters
setLeft hand operand of the subtract operator, as well as the target to store the result into.
operandRight hand operand of the subtract operator. NULL is considered to be the empty set.

Definition at line 408 of file amxc_set.c.

408  {
409  when_null(set, exit);
410  when_null(operand, exit);
411 
412  amxc_llist_iterate(it, &operand->list) {
414  amxc_flag_t* f = amxc_set_flag_find(set, fo->flag);
415  if(f == NULL) {
416  continue;
417  }
418  if(set->counted && (f->count > fo->count)) {
419  set->count -= fo->count;
420  f->count -= fo->count;
421  } else {
422  amxc_set_flag_delete(set, &f->it);
423  }
424  }
425 
426 exit:
427  return;
428 }

◆ amxc_set_symmetric_difference()

void amxc_set_symmetric_difference ( amxc_set_t *const  set,
const amxc_set_t *const  operand 
)

Calculates the symmetric difference of two sets.

The symmetric difference of two sets is the set of elements which are in either of the sets, but not in both. E.g. the symmetric difference of the sets {1,2,3} and {3,4} is {1,2,4}.

Parameters
setLeft hand operand of the operator, as well as the target to store the result into.
operandRight hand operand of the operator. NULL is considered to be the empty flag set.

Definition at line 463 of file amxc_set.c.

464  {
465  amxc_set_t* tmp = NULL;
466 
467  when_null(set, exit);
468  when_null(operand, exit);
469 
470  tmp = amxc_set_copy(operand);
471  when_null(tmp, exit);
472 
473  amxc_set_subtract(tmp, set);
474  amxc_set_subtract(set, operand);
475  amxc_set_union(set, tmp);
476 
477  amxc_set_delete(&tmp);
478 exit:
479  return;
480 }
amxc_set_t * amxc_set_copy(const amxc_set_t *const set)
Copies a set.
Definition: amxc_set.c:187
void amxc_set_delete(amxc_set_t **set)
Frees a set.
Definition: amxc_set.c:151
void amxc_set_subtract(amxc_set_t *const set, const amxc_set_t *const operand)
Subtract a set from another set.
Definition: amxc_set.c:408

◆ amxc_set_to_string()

char* amxc_set_to_string ( const amxc_set_t *const  set)

Converts a set to a space-separated string of flags.

Parameters
setThe flag set to convert.
Returns
A string holding the space-separated string of flags. It's allocated on the heap and needs to be freed by the caller with free(). A NULL pointer is returned if the set is NULL, empty or if memory allocation failed.

Definition at line 301 of file amxc_set.c.

301  {
302  return amxc_set_to_string_sep(set, " ");
303 }
char * amxc_set_to_string_sep(const amxc_set_t *const set, const char *sep)
Converts a set to a separated string of flags.
Definition: amxc_set.c:264

◆ amxc_set_to_string_sep()

char* amxc_set_to_string_sep ( const amxc_set_t *const  set,
const char *  sep 
)

Converts a set to a separated string of flags.

Parameters
setThe flag set to convert.
sepThe separation string.
Returns
A string holding the separated string of flags. It's allocated on the heap and needs to be freed by the caller with free(). A NULL pointer is returned if the set is NULL, empty or if memory allocation failed.

Definition at line 264 of file amxc_set.c.

264  {
265  int n = 0;
266  char* buf = NULL;
267  char* bufptr = NULL;
268  char countbuf[16];
269  int started = 0;
270 
271  when_null(set, exit);
272  when_null(sep, exit);
273 
274  amxc_llist_iterate(it, &set->list) {
276  n += strlen(f->flag) + started;
277  if((f->count != 1) && set->counted) {
278  n += sprintf(countbuf, ":%d", f->count);
279  }
280  started = 1;
281  }
282  buf = (char*) calloc(n + 1, 1);
283  bufptr = buf;
284  when_null(buf, exit);
285 
286  started = 0;
287  amxc_llist_iterate(it, &set->list) {
289  if((f->count != 1) && set->counted) {
290  bufptr += sprintf(bufptr, "%s%s:%d", started ? sep : "", f->flag, f->count);
291  } else {
292  bufptr += sprintf(bufptr, "%s%s", started ? sep : "", f->flag);
293  }
294  started = 1;
295  }
296 
297 exit:
298  return buf;
299 }

◆ amxc_set_union()

void amxc_set_union ( amxc_set_t *const  set,
const amxc_set_t *const  operand 
)

Joins two sets.

All flags that are set in the set referenced by operand, but are not in the flag set referenced by set, are added to set. Additionally, for counted sets, the counter of each flag of set will be incremented by the counter of the corresponding flag in operand.

Parameters
setLeft hand operand of the union operator, as well as the target to store the result into.
operandRight hand operand of the union operator. NULL is considered to be the empty flag set.

Definition at line 365 of file amxc_set.c.

365  {
366  when_null(set, exit);
367  when_null(operand, exit);
368 
369  amxc_llist_iterate(it, &operand->list) {
371  amxc_flag_t* f = amxc_set_flag_find(set, fo->flag);
372  if(f == NULL) {
373  amxc_set_flag_add(set, fo->flag, 0, set->counted ? fo->count : 1);
374  } else if(set->counted) {
375  set->count += fo->count;
376  f->count += fo->count;
377  }
378  }
379 
380 exit:
381  return;
382 }