Is there a better way of searching enums???

I have an enumeration (below) to search. I would do a very simple switch; but I want to have the option of using bitwise OR on the values (e.g. function(option1|option2)). How can I check for this? Surely I don't have to do:
1
2
3
4
switch (options) {
    case OPTION1:
    case OPTION1|OPTION2|...|OPTIONn:
}

because not only will that give me repetitive strain injury and look stupid; but it would take up like 400 lines of code without even doing anything (except knowing what options it was passed). As the enum can change (I'll probably think of more stuff to add later) it is out of the question to do a switch or if... else ladder.

How can I do this properly?

Here's the enum:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum options {
    FIRSTOPT,   /* This should be left first, see the array below. */
    PARENT,     /* Execute the program in this process (exits this process) */
    CHILD,      /* Execute it in a child process */
    SIMUL,      /* Execute the program in two child processes simultaneously */
    TIME,       /* Time the execution of the process(s) */
    RETURNVAL,  /* Get the return value of the process(s) */
    LASTOPT     /* This should be left last; see the array below */
}   opts[LASTOPT - FIRSTOPT]; /* This is to get the amount of options >:)
                               * because the value of last option is the amount
                               * of options starting from option 1 (in this case,
                               * 1).
                               */
/* These CAN be |'d, e.g. exec("/bin/program", CHILD|TIME|RETURNVAL);
 * However you should use your common sense. PARENT cannot be |'d with anything
 * other than SIMUL; which runs three processes (two children and the parent).
 */
Last edited on
I don't understand. If you PARENT|SIMUL, you just get SIMUL. PARENT==1 and SIMUL==3 (I think. I'm not sure if the compiler even assigns any particular sequence by default). Normally, the way flags are set up, each flag is a power of two so that no flag can overwrite another. That pretty much limits how many flags you can have to 32 or 64.

I also don't understand the point of the array opts.

The standard way to check a flag is ((x&flag)==flag). Flags are supposed to be independent from one another, so you don't check them in combination.

Finally, I don't think an enum is the best place to keep flag constants. I'd use macros or constants, depending on my mood.
I don't understand. If you PARENT|SIMUL, you just get SIMUL. PARENT==1 and SIMUL==3

Ah. Major pitfall.
(I think. I'm not sure if the compiler even assigns any particular sequence by default).

It does; I think ANSI says so. The first enumeration is always 0 unless otherwise set; and the ones after it are always the value of the previous enumeration + 1. So if you wanted negatives you'd have to either reverse the list, remember to do Enumeration = -Enumeration or just assign them yourself.

I also don't understand the point of the array opts.

The purpose of the array is to have the same amount of elements as there are options. For example, FIRSTOPT is 0 and LASTOPT is 7. So LASTOPT - FIRSTOPT is 7. So the size in bytes of the array divided by the size in bytes of it's first element (the type itself) is the amount of elements in the array, which is LASTOPT - FIRSTOPT - 1. Therefore with a simple macro:
#define SZ_ARRAY(array) ((sizeof(array)) / sizeof(*array))
I can get the amount of options so I don't have to hard-code it (means I only have to change one thing; so I'm less likely to forget how many enumerations there are because I can just do an SZ_ARRAY(opts) + 1 (for the 0 element).


The standard way to check a flag is ((x&flag)==flag). Flags are supposed to be independent from one another, so you don't check them in combination.

Finally, I don't think an enum is the best place to keep flag constants. I'd use macros or constants, depending on my mood.

Ok. I'll do it like that.


But then; how do they implement options like you get in SDL functions; e.g.
screen = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)? I always assumed that was an enumerated list of possibilities and they got the value of the |... How does that work? That's what I'm trying to do.
If you just wanted the amount of enums, you could have used
1
2
3
4
enum{
    //...
    N
};

Wow. That was hard.

how do they implement options like you get in SDL functions
I said
Normally, the way flags are set up, each flag is a power of two so that no flag can overwrite another.
1
2
3
4
#define flag0 1
#define flag1 2
#define flag2 4
#define flag3 8 

For your particular question, you could have just checked SDL.h:
1
2
3
4
5
6
7
8
#define	SDL_INIT_TIMER		0x00000001
#define SDL_INIT_AUDIO		0x00000010
#define SDL_INIT_VIDEO		0x00000020
#define SDL_INIT_CDROM		0x00000100
#define SDL_INIT_JOYSTICK	0x00000200
#define SDL_INIT_NOPARACHUTE	0x00100000	/* Don't catch fatal signals */
#define SDL_INIT_EVENTTHREAD	0x01000000	/* Not supported on all OS's */
#define SDL_INIT_EVERYTHING	0x0000FFFF 
Oh yeah... :l
I feel silly.

New new buttons!
I'm still not really understanding this... How do I check for multiple flags? I check if [number] & flag == flag... So I should check x & userFlag against myFlag?
Like this:
1
2
3
4
5
6
7
8
bool aFlag_used, anotherFlag_used = aFlag_used = false;
for (int i = 0; i < amount_of_flags; i++) {
    if ((i & option) == aFlag) {
        aFlag_used = true;
    } else if ((i & option) == anotherFlag) {
        anotherFlag_used = true;
    } // ...
}
?

Or should the value of i be the value of a valid flag? I don't understand that part... I'll have a look at the SDL source actually...

Never mind, open-source software has come to the rescue again:
if ( (flags & SDL_INIT_VIDEO) && !(SDL_initialized & SDL_INIT_VIDEO) )

I understand now.
Last edited on
That's not the most suitable check if you have a flag that's actually a combination of two flags.
The best way to check a flag is
1
2
3
#define CHECK_FLAG(x,flag) (((x)&(flag))==(flag))

if (CHECK_FLAG(x,flag))
Last edited on
What happened to working with enum? Helios is correct about the definition of values but there is no reason that macros are needed is there? You could certainly accomplish the same thing with the enum and and inline functions.

1
2
3
4
5
6
7
enum eStates
{
   STATEA= 1,
   STATEB = 2,
   STATEC = 4, 
   STATED = 8 // and so forth
};
Agreed. The problem with the example is that it is mixing two types of numbers: indices and bit-values.

The one that gives you an index (into an array and the like) is a normal, whole number: 0, 1, 2, 3, 4, etc.

The one that is a bit value is not necessarily correlated -- though for a straightly disjoint set it could correlate as bit-indices: 1, 2, 4, 8, 16, etc.

The point of bit-values is essentially that it is a packed array of booleans (represented by individual bits). The STL vector class actually has a specialization that does this (vector<bool> -- a design mistake, BTW).

If you really need additional information than a simple boolean bit, then you need to keep track of things separately. What exactly are you trying to accomplish? Perhaps we can suggest a better way... Does it need to be C-compatible, or can C++ stuff be used?
Topic archived. No new replies allowed.