Binary set - how to calculate offset?

Discussion in 'C Programming' started by A. Farber, May 4, 2007.

  1. A. Farber

    A. Farber Guest

    Hello C programmers,

    I have a small web game with the server part written in C
    which runs on OpenBSD (Linux and Cygwin work too).

    I've found out, that for me it's most comfortable to
    make the different player states to be of power of 2:

    typedef enum user_phase {
    CONNECTING = 0,
    CHAT_LOBBY = 1,
    CHAT_TABLE = 2,
    KIBITZING = 4,
    BIDDING_1 = 8,
    TAKING_TALON_1 = 16,
    TAKING_TALON_2 = 32,
    DISCARDING_1 = 64,
    DISCARDING_2 = 128,
    DECLARING = 256,
    BIDDING_2 = 512,
    ALL_PASSED = 1024,
    PLAYING = 2048,
    PHASE_MAX = 4096
    } user_phase;

    /* all phases from above except CONNECTING */
    #define ALL_PHASES ((uint32_t) 0xFFFFFFFF)

    That way I can check quickly for several phases
    at once, for example here in event handling table:

    static const EVENT_ENTRY EVENT_TABLE[] = {
    /* valid phases args table turn */
    { ALL_PHASES, NO, ANY, ANY, handle_alive },
    { ALL_PHASES, YES, ANY, ANY, handle_chat },
    { ALL_PHASES ^ KIBITZING, NO, ANY, NO, handle_kuku },
    { CHAT_LOBBY, YES, NO, ANY, handle_join },
    { ALL_PHASES ^ CHAT_LOBBY, NO, YES, ANY, handle_lobby },
    { BIDDING_1 | BIDDING_2, YES, YES, YES, handle_bid },
    { ALL_PASSED | PLAYING, YES, YES, YES, handle_card }
    };

    However my problem is to perform the backward
    mapping: given a user_phase, how do I found out,
    which power of 2 is it (sorry for my awkward language)?

    For example here how I find phase names currently:

    static const char* PHASE_NAMES[] = {
    "CONNECTING",
    "CHAT_LOBBY",
    "CHAT_TABLE",
    "KIBITZING",
    "BIDDING_1",
    "TAKING_TALON_1",
    "TAKING_TALON_2",
    "DISCARDING_1",
    "DISCARDING_2",
    "DECLARING",
    "BIDDING_2",
    "ALL_PASSED",
    "PLAYING"
    };

    const char*
    phase_name(user_phase phase)
    {
    unsigned i;

    for (i = 0; i < sizeof(PHASE_NAMES) / sizeof(char*); i++)
    if ((uint32_t)(1 << i) == phase)
    return PHASE_NAMES;

    return "UNKNOWN";
    }

    Is there a better way maybe?

    Thank you
    Alex
     
    A. Farber, May 4, 2007
    #1
    1. Advertising

  2. A. Farber

    Eric Sosman Guest

    A. Farber wrote On 05/04/07 10:26,:
    > [...]
    >
    > However my problem is to perform the backward
    > mapping: given a user_phase, how do I found out,
    > which power of 2 is it (sorry for my awkward language)?


    (The snipped material makes clear that user_phase
    is an enum value equal to a positive integral power of 2.)

    Stripped to its essentials, you are looking for the
    binary logarithm of a value. There are many ways to do
    this, some of which are described at

    http://graphics.stanford.edu/~seander/bithacks.html

    WARNING: Some of the hacks on this page rely on non-portable
    assumptions, not always mentioned explicitly. Be alert!
    Also, the claims about operation count, branch counts, and
    so on are strongly platform-dependent.

    --
     
    Eric Sosman, May 4, 2007
    #2
    1. Advertising

  3. A. Farber

    Old Wolf Guest

    On May 5, 2:26 am, "A. Farber" <> wrote:
    > I've found out, that for me it's most comfortable to
    > make the different player states to be of power of 2:
    >
    > typedef enum user_phase {
    > CONNECTING = 0,
    > CHAT_LOBBY = 1,
    > CHAT_TABLE = 2,

    [...]
    > PLAYING = 2048,
    > PHASE_MAX = 4096


    I find it is clearer to use hexadecimal constants in this
    situation; it also helps to reduce typoes, sign, and
    out-of-range constant problems.

    > /* all phases from above except CONNECTING */
    > #define ALL_PHASES ((uint32_t) 0xFFFFFFFF)


    What is the purpose of that cast?

    NB. 0xFFFFFFFF is already an unsigned int (unless you
    are on a system where int is less than 32 bits, in which
    the code is still correct but it will be a long or an unsigned
    long).

    > That way I can check quickly for several phases
    > at once, for example here in event handling table:
    >
    > static const EVENT_ENTRY EVENT_TABLE[] = {


    A minor point; uppercase identifiers starting with E are
    reserved for implementation use whenever <errno.h> is
    included. Suppose you were coding on an embedded
    air conditioning system, the system vendor might have
    defined an error condition where the entry to an air vent
    was malfunctioning: E VENT_ENTRY !

    > /* valid phases args table turn */


    > { CHAT_LOBBY, YES, NO, ANY, handle_join },
    > { ALL_PHASES ^ CHAT_LOBBY, NO, YES, ANY, handle_lobby },
    > { BIDDING_1 | BIDDING_2, YES, YES, YES, handle_bid },
    > { ALL_PASSED | PLAYING, YES, YES, YES, handle_card }
    >
    > However my problem is to perform the backward
    > mapping: given a user_phase, how do I found out,
    > which power of 2 is it (sorry for my awkward language)?


    They way I do such things is (note, I like to always
    prefix my enums to avoid unexpected clashes and
    avoid causing undefind behaviour if one starts with E):

    enum
    { PHASE_NONE
    , PHASE_FOO
    , PHASE_BAR
    , PHASE_QUX
    , NUM_PHASES
    };

    char const *phase_names[] =
    { "(none)"
    , "foo"
    , "bar"
    , "qux"
    };

    STATIC_ASSERT( NUM_PHASES == dimof(phase_names) );

    Note, this can be hard to keep in sync if the tables are
    large. So it is possible to combine those two into one file, eg.
    MAGIC( PHASE_FOO, "foo" )
    MAGIC( PHASE_BAR, "bar" )
    and then include this file in both your .h and .c files but
    with MAGIC defined to produce the enum if it is a .h, and
    produce the string table if it is a .c .

    For the flags table, assuming your goal is compactness:
    #define FT(X) P_##X = 1UL << PHASE_##X
    enum
    { FT(FOO)
    , FT(BAR)
    , FT(QUX)
    };
    #undef FT

    then the table will look like:
    { P_ALL_PASSED | P_PLAYING, YES, YES, YES, handle_card }
    etc.
     
    Old Wolf, May 7, 2007
    #3
  4. On 6 May 2007 16:03:28 -0700, Old Wolf <> wrote:
    <snip>
    > > #define ALL_PHASES ((uint32_t) 0xFFFFFFFF)


    > NB. 0xFFFFFFFF is already an unsigned int (unless you
    > are on a system where int is less than 32 bits, in which
    > the code is still correct but it will be a long or an unsigned
    > long).
    >

    Or int is more than 32 (nonpadding) bits in which case that fits in,
    and is, signed int. (Although it would then safely promote to unsigned
    int where needed in an expression, which is probably enough.)

    > enum
    > { PHASE_NONE
    > , PHASE_FOO
    > , PHASE_BAR
    > , PHASE_QUX


    BTW the canonical metaname is quux with two u's. Not to be confused
    with two yous, two ewes, you toos, U-2s, yoohoos, tutus, or youse. <G>

    - formerly david.thompson1 || achar(64) || worldnet.att.net
     
    David Thompson, May 21, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lance Riedel

    Translated Offset to Source Offset

    Lance Riedel, Oct 14, 2003, in forum: XML
    Replies:
    2
    Views:
    526
    Patrick TJ McPhee
    Oct 15, 2003
  2. LaundroMat

    Calculate sha1 hash of a binary file

    LaundroMat, Aug 6, 2008, in forum: Python
    Replies:
    7
    Views:
    868
    LaundroMat
    Aug 7, 2008
  3. Mark Hobley
    Replies:
    11
    Views:
    936
    Seebs
    Apr 4, 2010
  4. Replies:
    2
    Views:
    317
  5. Roy Smith
    Replies:
    4
    Views:
    319
    Roy Smith
    Jan 27, 2013
Loading...

Share This Page