Home > Enterprise >  Converting enum type to a specific, predefined array of hex values in C
Converting enum type to a specific, predefined array of hex values in C

Time:04-09

What would be the most optimal and shortest way to write a function returning an array of 8-bit hex values, which are assigned based on an enumerated parameter.

I need to hard code commands, which will be sent over bluetooth and still have an easy access to them in code. So I have an enum with all possible commands listed in a human-readable way.

enum eventType {
    MODIFY_A,
    MODIFY_B,
    MODIFY_C,
    MODIFY_D
}

The communication protocol I try to adapt uses custom packets with predefined hex values. So for example, sending 0x00, 0x01, 0x02, 0x03 could change led colour of a receiving device.

The library used for ble communication accepts arrays of said hexes, or other words, just a plain C string.

It would be easiest to simply define an array in a switch() after declaring it, just like this:

uint8_t* getCommandOf(eventType event) {
    uint8_t command[4];
     
    switch(event) {
        case eventType::MODIFY_A:
            command = {0x01, 0x00, 0x00, 0x00}; break; 
        case eventType::MODIFY_B:
            command = {0x02, 0x00, 0x00, 0x00}; break; 
        case eventType::MODIFY_C:
            command = {0x03, 0x00, 0x00, 0x00}; break; 
        case eventType::MODIFY_D:
            command = {0x04, 0x00, 0x00, 0x00}; break; 
    }

    return command;
}

Then I could simply call: sendOverBLE(getCommandOf(eventType::MODIFY_A));

Unfortunately, we can't do that in C . I'm open to suggestions. How would you solve it? I though of a few solutions, butI don't like any of them.

Maybe define them in a 2d array? Or a custom container class?

CodePudding user response:

I would suggest using and returning a std::array. That would change your function to

std::array<uint8_t, 4> getCommandOf(eventType event) {
    switch(event) {
        case eventType::MODIFY_A:
            return {0x01, 0x00, 0x00, 0x00};
        case eventType::MODIFY_B:
            return {0x02, 0x00, 0x00, 0x00};
        case eventType::MODIFY_C:
            return {0x03, 0x00, 0x00, 0x00};
        case eventType::MODIFY_D:
            return {0x04, 0x00, 0x00, 0x00}; 
    }
    // for bad input
    return {}; // for all zeros
    // or use an exception
    throw std::invalid_argument("some error message here");
}

If you need to pass this array to a function that takes a uint8_t*, then you can use array's data member to get such a pointer like

my_uint8_t_ptr_func(getCommandOf(eventType::MODIFY_A).data());

CodePudding user response:

If you're in complete control over your enum you could define it as follows:

enum eventType : uint8_t {
    MODIFY_A = 1,
    MODIFY_B,
    MODIFY_C,
    MODIFY_D
}

Then your function could be:

std::array<uint8_t, 4> getCommandOf(eventType event) {
    return { event, 0, 0, 0 };
}
  • Related