Updated LICENSE to MIT
Added dynamic enum, via mutable array of struct
Added example of better enum in C, done using structs
Due to being simple alias for integers, C enums are not type-safe. This means that an enum could be initialized using another one without the compiler (at least GCC) complaining.
Moreover, parsing from integer and conversion to string is cumbersome. It requires, in the worst case of non-consecutive enum values, a switch case for each operation. These switch-case must be kept aligned with the enum variants, especially if a new one is added.
Using struct instances as enum variants could mitigate the issues of enum, while keeping a lot of their convenience.
A struct like this could be assigned an integer and a string representation. This way the two are always aligned and the variant to string conversion is simplified.
typedef struct {
int num;
const char *const label;
} BAR_OPTION;
The collection of variants could be stored in an array, like this. The number of elements then comes for free and it is updated along with the array.
const BAR_OPTION BAR_OPTION_A = {BAR_OPTION_A_raw, "BAR: OPTION_A"};
const BAR_OPTION BAR_OPTION_B = {BAR_OPTION_B_raw, "BAR: OPTION_B"};
const BAR_OPTION BAR_OPTION_C = {BAR_OPTION_C_raw, "BAR: OPTION_C"};
static const BAR_OPTION *const BAR_OPTIONS[] = {&BAR_OPTION_A, &BAR_OPTION_B, &BAR_OPTION_C};
const int NUMBER_OF_BAR_OPTIONS = sizeof(BAR_OPTIONS) / sizeof(BAR_OPTIONS[0]);
As an additional point, the BAR_OPTIONS
array could be made mutable,
to allow registering more variants dynamically.
With respect to the static approach, only these two functions are added.
bool BAZ_OPTION_register(const BAZ_OPTION *const new_choice);
bool BAZ_OPTION_unregister(const BAZ_OPTION *const new_choice);
Overall, this struct-as-enum strategy offers interesting advantages at the cost of a slightly higher number of rows.