I want to make this clear up front : I know how this trick works, what I want is a link to a clear explanation to share with others.
One of the answers to a C macro question talks about the "X macro" or "not yet defined macro" idiom. This involves defining something like:
#define MAGIC_LIST \
X(name_1, default_1) \
X(name_2, default_2) \
...
Then to create, say, an array of values with named indices you do:
typedef enum {
#define X(name, val) name,
MAGIC_LIST
#undef X
} NamedDefaults;
You can repeat the procedure with a different #define for X() to create an array of values, and maybe debugging strings, etc.
I'd like a link to a clear explanation of how this works, pitched at someone who is passably familiar with C. I have no idea what everyone usually calls this pattern, though, so my attempts to search the web for it have failed thus far.
(If there is such an explanation on SO, that'd be fine...)
The Wikipedia page about the C preprocessor mentions it but is not brilliantly clear IMO:
http://en.wikipedia.org/wiki/C_preprocessor#X-Macros
I wrote a paper about it for my group; feel free to use this if you wish.
/* X-macros are a way to use the C pre-processor to provide tuple-like
* functionality that would not otherwise be easy to implement in C.
* Any time you find yourself writing a comment that says something
* like "These values must be kept in sync with the values in typedef enum
* foo_t", or adding a new item to a list and copying and pasting functions
* to handle it, then X-macros are probably a better way to implement the
* behaviour you want.
*/
/* Begin with the main definition of the table of tuples. This can be directly
* in the header file, or in a separate #included template file. This example
* is from some hardware revision reporting code.
*/
/*
* Board versions
* Upper bound resistor value, hardware version, hardware version string
*/
#define APP_HW_VERSIONS \
X(0, HW_UNKNOWN, UNKNOWN_HW_VER) \
X(8, HW_NO_VERSION, "XDEV") /* Unversioned board (e.g. dev board) */ \
X(24, HW_REVA, "REVA") \
X(39, HW_REVB, "REVB") \
X(54, HW_REVD, "REVD") \
X(71, HW_REVE, "REVE") \
X(88, HW_REVF, "REVF") \
X(103,HW_REVG, "REVG") \
X(118,HW_REVH, "REVH") \
X(137,HW_REVI, "REVI") \
X(154,HW_REVJ, "REVJ") \
/* add new versions above here */ \
X(255,HW_REVX, "REVX") /* Unknown newer version */
/* Now, any time you need to use the contents of this table, you redefine the
* X(a,b,c) macro to give the behaviour you want. In the hardware revision
* example, the first thing we need is an enumerated type giving the
* possible options for the value of the hardware revision.
*/
#define X(a,b,c) b,
typedef enum {
APP_HW_VERSIONS
} app_hardware_version_t;
#undef X
/* The next thing we need in this example is some code to extract the
* hardware revision from the value of the version resistors.
*/
static app_hardware_version_t read_board_version(
board_aio_id_t identifier,
board_aio_val_t value
)
{
app_hardware_version_t app_hw_version;
/* Determine board version based on ADC reading */
#define X(a,b,c) if (value < a) {app_hw_version = b;} else
APP_HW_VERSIONS
#undef X
{
app_hw_version = HW_UNKNOWN;
}
return app_hw_version;
}
/* Now we have two different places that need to extract the hardware revision
* as a string: the MMI info screen and the ATI command.
*/
/* in the info screen code: */
switch(ver)
{
#define X(a,b,c) case b: ascii_to_display_string((lcd_char_t *) &app[0], c, HW_VER_STRING_LEN); break;
APP_HW_VERSIONS
#undef X
default:
ascii_to_display_string((lcd_char_t *) &app[0], UNKNOWN_HW_VER, HW_VER_STRING_LEN);
break;
}
/* in the ATI handling code: */
switch(ver)
{
#define X(a,b,c) case b: strncpy(&p_data, (const uint8_t *) c, HW_VER_STRING_LEN); break;
APP_HW_VERSIONS
#undef X
default:
strncpy_write(&p_data, (const uint8_t *) UNKNOWN_HW_VER, HW_VER_STRING_LEN);
break;
}
/* Another common example use case is auto-generation of accessor and mutator
* functions for a list of storage keys
*/
/* First the tuple table */
/* Configuration items:
* Storage key ID, name, type, min value, max value
*/
#define CONFIG_ITEMS \
X(1234, DEVICE_ID, uint16_t, 0, 0xFFFF) \
X(1235, NUM_CONNECTIONS, uint8_t, 0, 8) \
X(1236, ENABLE_LOGGING, bool_t, 0, 1) \
X(1237, SECURITY_KEY, uint32_t, 0, 0xFFFFFFFF)
/* add new items above here */
/* Generate the enumerated type of keys */
#define X(a,b,c,d,e) CONFIG_ITEM_##b = a,
typedef enum {
CONFIG_ITEMS
} config_item_t;
#undef X
/* Generate the accessor functions */
#define X(a,b,c,d,e) \
int get_config_item_##b(void *p_buf) \
{ \
return read_from_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
/* Generate the mutator functions */
#define X(a,b,c,d,e) \
bool_t set_config_item_##b(void *p_buf) \
{ \
c val = * (c*) p_buf; \
if (val < d || val > e) return FALSE; \
return write_to_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
/* Or, if you prefer, one big generic accessor function */
int get_config_item(config_item_t id, void *p_buf)
{
switch (id)
{
#define X(a,b,c,d,e) case a: return read_from_key(a, sizeof(c), p_buf); break;
CONFIG_ITEMS
#undef X
default:
return 0;
}
}
/* and one big generic mutator function */
bool_t set_config_item(config_item_t id, void *p_buf)
{
switch (id)
{
#define X(a,b,c,d,e) \
case a: \
{ \
c val = * (c*) p_buf; \
if (val < d || val > e) return FALSE; \
return write_to_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
default:
return FALSE;
}
}
/* Finally let's add a logging function to dump all the config items */
void log_config_items(void)
{
#define X(a,b,c,d,e) \
{ \
c val; \
if (read_from_key(a, sizeof(c), &val) == sizeof(c)) \
{ printf("CONFIG_ITEM_##b (##a): 0x%x\n", val); } \
else { printf("CONFIG_ITEM_##b (##a): Failed to read\n"); } \
}
CONFIG_ITEMS
#undef X
}
/* Now, when you need to add a new item to your list of config keys, you don't
* need to update the enumerated type and copy and paste new get and set
* functions for each new key; you simply update the table of tuples and the
* pre-processor takes care of the rest.
*/
Related
I have implemented a queue in C language with usage of an array of structures.
typedef struct{
req_t buffer[BUFFER_SIZE]; // buffer
uint16_t size; // length of the queue
uint16_t count; // number of elements present in the queue
req_t *p_head; // pointer to head of the queue (read end)
req_t *p_tail; // pointer to tail of the queue (write end)
}circular_buffer_t;
void init_cb(circular_buffer_t *p_cb){
p_cb->p_head = p_cb->buffer;
p_cb->p_tail = p_cb->buffer;
p_cb->count = 0;
p_cb->size = BUFFER_SIZE;
}
The problem is that above given implementation is usable only for storing the
instances of req_t structures. Now I need to store instances of another
structure and I don't know how to define the queue in more general way so that
I will be able to use same queue for instances of different structures. Problem
is that I need to know the structure type before buffer definition. Does anybody
have any idea how to solve that?
#ifndef CIRCULAR_BUFFER_H_
#define CIRCULAR_BUFFER_H_
#define BUFFER_SIZE 32
// macro creates variant of the queue for each struct type
#define define_queue(TYPE) \
\
// queue element definition \
typedef struct{ \
TYPE buffer[BUFFER_SIZE]; \
uint16_t size; \
uint16_t count; \
TYPE *p_head; \
TYPE *p_tail; \
}circular_buffer_##TYPE##_t \
\
\
// queue init function definition \
void init_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb){ \
p_cb->p_head = p_cb->buffer; \
p_cb->p_tail = p_cb->buffer; \
p_cb->count = 0; \
p_cb->size = BUFFER_SIZE; \
} \
\
// queue enqueue function definition \
BOOL enqueue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE *p_enq_elem){ \
\
if(p_cb->count < p_cb->size){ \
\
taskENTER_CRITICAL(); \
\
*(p_cb->p_tail) = *p_enq_elem; \
p_cb->p_tail = ((++(p_cb->p_tail) == (p_cb->buffer + p_cb->size)) ? \
(p_cb->buffer) : (p_cb->p_tail)); \
p_cb->count++; \
\
taskEXIT_CRITICAL(); \
\
return TRUE; \
\
}else{ \
\
return FALSE; \
\
} \
\
} \
\
// queue dequeue function definition \
BOOL dequeue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE *p_deq_elem){ \
\
if((p_cb->count) != 0){ \
\
taskENTER_CRITICAL(); \
\
*p_deq_elem = *(p_cb->p_head); \
p_cb->p_head = ((++(p_cb->p_head) == (p_cb->buffer + p_cb->size)) ? \
(p_cb->buffer) : (p_cb->p_head)); \
p_cb->count--; \
\
taskEXIT_CRITICAL(); \
\
return TRUE; \
\
}else{ \
\
return FALSE; \
\
} \
\
} \
// macros for functions declarations
#define declare_init_cb(TYPE) void init_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb)
#define declare_enqueue_cb(TYPE) BOOL enqueue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE p_enq_elem);
#define declare_dequeue_cb(TYPE) BOOL dequeue_cb_##TYPE(circular_buffer_##TYPE##_t *p_cb, TYPE p_deq_elem);
#endif
Structures I am going to use with the queue
typedef struct{
uint32_t addr; // address of the alarm signal
BOOL critical; // alarm is critical (=TRUE), alarm is non critical (=FALSE)
BOOL set; // alarm was set (=TRUE)
BOOL cleared; // alarm was cleared (=TRUE)
BOOL communicated; // alarm is communicated to Main Controller (=TRUE)
uint8_t code; // alarm code (0 - 255) - permanently 180
uint8_t no; // alarm number (0 - 255)
uint8_t no_flashes; // number of LED flashes if the alarm is active
}alarm_t;
and
typedef struct{
msg_e req_type; // request type
uint8_t blk_no; // block number
uint8_t no_records; // number of influenced records
uint8_t data_id[MAX_NO_RECORDS]; // data id, max. number of records in one block
uint16_t value[MAX_NO_RECORDS]; // written value, max. number of records in one block
uint8_t cleared_alarm_no; // number of the alarm which should be cleared
uint8_t flash_load; // 0 = Go into flash load mode
uint8_t mode[6]; // 000000 - Normal, BOOTBL - Boot block
uint8_t data_block[BLOCK_SIZE]; // one block in flash memory
uint8_t flash_page_number; // page number in flash memory (starting at 1)
uint8_t flash_block_number; // block number in flash memory (starting at 1)
}req_t;
If you want to store any type of struct in your queue, you have to use void * type and store in the queue only the pointers to any structs.
typedef struct{
void *buffer[BUFFER_SIZE]; // buffer
uint16_t size; // length of the queue
uint16_t count; // number of elements present in the queue
void *p_head; // pointer to head of the queue (read end)
void *p_tail; // pointer to tail of the queue (write end)
}circular_buffer_t;
Then, you have just to put any pointer in your queue like this:
circular_buffer_t p_cb;
my_struct_t *my_struct = malloc(sizeof(my_struct_t));
// set
p_cb.buffer[0] = (void*)my_struct;
// get
(my_struct_t*)p_cb.buffer[0];
1. Storing structs by value
If you specify the struct size when creating the queue, you can use it to store actual structs (copied by value) into the buffer.
typedef struct {
u32 capacity;
u32 element_size;
u8 * head; // next free slot
u8 * tail; // oldest enqueued item
u8 * buffer;
u8 * buffer_end;
} circular_buffer_t;
void circbuff_init(circular_buffer_t *p_cb, u8 *buffer, u32 element_size, u32 capacity)
{
p_cb->capacity = capacity;
p_cb->element_size = element_size;
p_cb->buffer = buffer;
p_cb->buffer_end = buffer + (capacity * element_size);
p_cb->head = buffer;
p_cb->tail = buffer;
}
Note that .count is redundant, you can calculate it at any time, and removing it makes reader/writer syncronization easier (in case that you read and write from different interrupts).
You need to take care to pass the correct buffer size and element_size:
circbuff_init(p_cb, buffer, sizeof(SomeStruct), sizeof(buffer) / sizeof(SomeStruct));
And then you just copy each element:
bool circbuff_dequeue(circular_buffer_t *hnd, void *dst)
{
// if empty, do nothing
if (circbuff_isEmpty(hnd))
return false;
memcpy(dst, hnd->tail, hnd->element_size);
hnd->tail = modulo_increment(hnd, hnd->tail);
return true;
}
2. Storing pointers to structs
This is already mentioned in some other answer.
3. Using a macro to create a typed buffer for each struct type
This is similar to how klib works. You would have to call certain macros to define each concrete type of circular buffer (for each struct), but then you would have compile time type safety.
Like I've mentioned in my comment above, I'd recommend using a union to store different types in one queue slot. Additionally, some type indicator is needed to distinguish them. Here's an example:
First, redefine req_t as req_t1, adding a type indicator as the first member:
typedef struct _req_t1
{
int type;
// append the members of your first structure here
}
req_t1;
Define the second type to be stored in an analogous way as req_t2:
typedef struct _req_t2
{
int type;
// append the members of your second structure here
}
req_t2;
Now redefine req_t as a union, containing both types, plus a standalone member that represents the type indicator, in order to test for the stored type:
typedef union _req_t
{
int type;
req_t1 item1;
req_t2 item2;
}
req_t;
Now you can use your circular buffer as before. However, req_t is now a compound member that might be interpreted as either type.
typedef struct _circular_buffer_t
{
req_t buffer [BUFFER_SIZE]; // buffer
uint16_t size; // length of the queue
uint16_t count; // number of elements present in the queue
req_t *p_head; // pointer to head of the queue (read end)
req_t *p_tail; // pointer to tail of the queue (write end)
}
circular_buffer_t;
To access the head, you use p_head->type to identify the type that's contained in this slot. If it indicates req_t1, you use p_head->item1 to access the members of req_t1, otherwise p_head->item2 for req_t2. This approach can be extended to any number of types.
What you want, is in fact a structure with a generic type field. The C language doesn't provide support for that. The best you can do it's to try to emulate that behavior. One way to do that is using macros or using generic pointers. Look here for more info about that: Pseudo-generics in C
I have a set of #defines like these:
#define MODULE1_PINMASK 0x1
#define MODULE2_PINMASK 0x2
#define MODULE3_PINMASK 0x3
where the value of the pinmask depends on the second argument of:
#define MODULE1_PORT_PIN A,1
#define MODULE2_PORT_PIN A,2
#define MODULE3_PORT_PIN A,3
If at any point in future, I make a change, e.g:
#define MODULE1_PORT_PIN A,1 /* changes to #define MODULE1_PORT_PIN A,4 */
I need to also change the pinmask:
#define MODULE1_PINMASK 0x1 /* then becomes #define MODULE1_PINMASK 0x4 */
I'm trying to automate the process by not having to manually change the pinmask. So far I've got these macros to extract the second argument of MODULEX_PORT_PIN (I don't care about the first argument in this case):
#define GET_SECOND(X, Y) Y
#define GET_PIN(PORT_PIN) GET_SECOND(PORT_PIN)
If i use them in functions, I get the correct result, for instance:
uint8_t pinmask=0x0;
switch (GET_PIN(MODULE2_PORT_PIN))
{
case 1:
pinmask = 0x1;
break;
case 2:
pinmask = 0x2;
break;
case 3:
pinmask = 0x3;
break;
default:
break;
}
printf ("%#x", pinmask); /* prints "0x2" */
but I want to keep the pinmasks as #defines. Is there a way to implement a #define GET_PINMASK macro which uses the switch case to define the pinmask? I'm aiming for something like:
#define MODULE1_PINMASK ASSIGN_PINMASK(GET_PIN(MODULE1_PORT_PIN))
which in this case would define MODULE1_PINMASK as 0x1.
EDIT: The second argument in #define MODULE1_PORT_PIN A,1 is an uint8_t and not a hex value and so I can't pass it directly.
I think you may be overthinking the problem. If the second field of each MODULEn_PORT_PIN define is always an integer constant expression, then this should work:
#define MODULE1_PORT_PIN A,1
#define MODULE2_PORT_PIN A,2
#define MODULE3_PORT_PIN A,3
#define GET_SECOND(X, Y) (Y)
#define PIN_TO_MASK(PIN) (1ul << GET_SECOND(PIN))
#define MODULE1_PINMASK PIN_TO_MASK(MODULE1_PORT_PIN)
#define MODULE2_PINMASK PIN_TO_MASK(MODULE2_PORT_PIN)
#define MODULE3_PINMASK PIN_TO_MASK(MODULE3_PORT_PIN)
It is not clear from your question whether the second field can be something other than an integer constant expression. If the second field ever involves an enum constant, then the MODULEn_PINMASK macros can still be used in any context except for #if expressions. If it ever involves a variable, then they can only be used inside the body of a function. (Since this is C and not C++, that's true even if the variable is const.)
There is no way to avoid having to write each #define individually. If that is a problem, you should be thinking about writing a program that generates the list of #defines. Generating source code from a DSL of your own invention, at build time, is an under-valued technique.
Have you considered using x-macros?
You start by creating an abstract #define for the list of entries:
#define CREATE_LIST() \
ENTRY(1, A, 0x1) \
ENTRY(2, A, 0x2) \
ENTRY(3, A, 0x3)
And then invoke the list for different definitions of ENTRY:
// Get the number of entries. Creates something like:
// const uint8_t PIN_COUNT = 0 + 1 + 1 + 1;
#define ENTRY(number, x, y) + 1
const uint8_t PIN_COUNT = \
CREATE_LIST()
;
#undef ENTRY
// Array of first parameters
#define ENTRY(number, x, y) #x ,
const char * Pin_names[PIN_COUNT] =
{
CREATE_LIST()
};
#undef ENTRY
// Array of second parameters
#define ENTRY(number, x, y) y,
const uint8_t Pin_masks[PIN_COUNT] =
{
CREATE_LIST()
};
#undef ENTRY
// Array of module names
#define ENTRY(number, x, y) STRINGIFY(MODULE ## number) ,
const char * Module_names[PIN_COUNT] =
{
CREATE_LIST()
};
#undef ENTRY
The preprocessor will expand this to something like:
const uint8_t PIN_COUNT =
+ 1 + 1 + 1
;
const char * Pin_names[PIN_COUNT] =
{
"A" , "A" , "A" ,
};
const uint8_t Pin_masks[PIN_COUNT] =
{
0x1, 0x2, 0x3,
};
const char * Module_names[PIN_COUNT] =
{
"MODULE1", "MODULE2", "MODULE3"
};
The possibilities are endless. It's less readable, but perhaps slightly more maintainable.
Is there a compile-time way to detect / prevent duplicate values within a C/C++ enumeration?
The catch is that there are multiple items which are initialized to explicit values.
Background:
I've inherited some C code such as the following:
#define BASE1_VAL (5)
#define BASE2_VAL (7)
typedef enum
{
MsgFoo1A = BASE1_VAL, // 5
MsgFoo1B, // 6
MsgFoo1C, // 7
MsgFoo1D, // 8
MsgFoo1E, // 9
MsgFoo2A = BASE2_VAL, // Uh oh! 7 again...
MsgFoo2B // Uh oh! 8 again...
} FOO;
The problem is that as the code grows & as developers add more messages to the MsgFoo1x group, eventually it overruns BASE2_VAL.
This code will eventually be migrated to C++, so if there is a C++-only solution (template magic?), that's OK -- but a solution that works with C and C++ is better.
There are a couple ways to check this compile time, but they might not always work for you. Start by inserting a "marker" enum value right before MsgFoo2A.
typedef enum
{
MsgFoo1A = BASE1_VAL,
MsgFoo1B,
MsgFoo1C,
MsgFoo1D,
MsgFoo1E,
MARKER_1_DONT_USE, /* Don't use this value, but leave it here. */
MsgFoo2A = BASE2_VAL,
MsgFoo2B
} FOO;
Now we need a way to ensure that MARKER_1_DONT_USE < BASE2_VAL at compile-time. There are two common techiques.
Negative size arrays
It is an error to declare an array with negative size. This looks a little ugly, but it works.
extern int IGNORE_ENUM_CHECK[MARKER_1_DONT_USE > BASE2_VAL ? -1 : 1];
Almost every compiler ever written will generate an error if MARKER_1_DONT_USE is greater than BASE_2_VAL. GCC spits out:
test.c:16: error: size of array ‘IGNORE_ENUM_CHECK’ is negative
Static assertions
If your compiler supports C11, you can use _Static_assert. Support for C11 is not ubiquitous, but your compiler may support _Static_assert anyway, especially since the corresponding feature in C++ is widely supported.
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
GCC spits out the following message:
test.c:16:1: error: static assertion failed: "Enum values overlap."
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
^
I didn't see "pretty" in your requirements, so I submit this solution implemented using the Boost Preprocessor library.
As an up-front disclaimer, I haven't used Boost.Preprocessor a whole lot and I've only tested this with the test cases presented here, so there could be bugs, and there may be an easier, cleaner way to do this. I certainly welcome comments, corrections, suggestions, insults, etc.
Here we go:
#include <boost/preprocessor.hpp>
#define EXPAND_ENUM_VALUE(r, data, i, elem) \
BOOST_PP_SEQ_ELEM(0, elem) \
BOOST_PP_IIF( \
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(elem), 2), \
= BOOST_PP_SEQ_ELEM(1, elem), \
BOOST_PP_EMPTY()) \
BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(data, BOOST_PP_ADD(i, 1)))
#define ADD_CASE_FOR_ENUM_VALUE(r, data, elem) \
case BOOST_PP_SEQ_ELEM(0, elem) : break;
#define DEFINE_UNIQUE_ENUM(name, values) \
enum name \
{ \
BOOST_PP_SEQ_FOR_EACH_I(EXPAND_ENUM_VALUE, \
BOOST_PP_SEQ_SIZE(values), values) \
}; \
\
namespace detail \
{ \
void UniqueEnumSanityCheck##name() \
{ \
switch (name()) \
{ \
BOOST_PP_SEQ_FOR_EACH(ADD_CASE_FOR_ENUM_VALUE, name, values) \
} \
} \
}
We can then use it like so:
DEFINE_UNIQUE_ENUM(DayOfWeek, ((Monday) (1))
((Tuesday) (2))
((Wednesday) )
((Thursday) (4)))
The enumerator value is optional; this code generates an enumeration equivalent to:
enum DayOfWeek
{
Monday = 1,
Tuesday = 2,
Wednesday,
Thursday = 4
};
It also generates a sanity-check function that contains a switch statement as described in Ben Voigt's answer. If we change the enumeration declaration such that we have non-unique enumerator values, e.g.,
DEFINE_UNIQUE_ENUM(DayOfWeek, ((Monday) (1))
((Tuesday) (2))
((Wednesday) )
((Thursday) (1)))
it will not compile (Visual C++ reports the expected error C2196: case value '1' already used).
Thanks also to Matthieu M., whose answer to another question got me interested in the Boost Preprocessor library.
I don't believe there's a way to detect this with the language itself, considering there are conceivable cases where you'd want two enumeration values to be the same. You can, however, always ensure all explicitly set items are at the top of the list:
typedef enum
{
MsgFoo1A = BASE1_VAL, // 5
MsgFoo2A = BASE2_VAL, // 7
MsgFoo1B, // 8
MsgFoo1C, // 9
MsgFoo1D, // 10
MsgFoo1E, // 11
MsgFoo2B // 12
} FOO;
So long as assigned values are at the top, no collision is possible, unless for some reason the macros expand to values which are the same.
Usually this problem is overcome by giving a fixed number of bits for each MsgFooX group, and ensuring each group does not overflow it's allotted number of bits. The "Number of bits" solution is nice because it allows a bitwise test to determine to which message group something belongs. But there's no built-in language feature to do this because there are legitimate cases for an enum having two of the same value:
typedef enum
{
gray = 4, //Gr[ae]y should be the same
grey = 4,
color = 5, //Also makes sense in some cases
couleur = 5
} FOO;
I don't know of anything that will automatically check all enum members, but if you want to check that future changes to the initializers (or the macros they rely on) don't cause collisions:
switch (0) {
case MsgFoo1A: break;
case MsgFoo1B: break;
case MsgFoo1C: break;
case MsgFoo1D: break;
case MsgFoo1E: break;
case MsgFoo2A: break;
case MsgFoo2B: break;
}
will cause a compiler error if any of the integral values is reused, and most compilers will even tell you what value (the numeric value) was a problem.
You could roll a more robust solution of defining enums using Boost.Preprocessor - wether its worth the time is a different matter.
If you are moving to C++ anyway, maybe the (proposed) Boost.Enum suits you (available via the Boost Vault).
Another approach might be to use something like gccxml (or more comfortably pygccxml) to identify candidates for manual inspection.
While we do not have full on reflection, you can solve this problem if you can relist the enumeration values.
Somewhere this is declared:
enum E { A = 0, B = 0 };
elsewhere, we build this machinery:
template<typename S, S s0, S... s>
struct first_not_same_as_rest : std::true_type {};
template<typename S, S s0, S s1, S... s>
struct first_not_same_as_rest : std::integral_constant< bool,
(s0 != s1) && first_not_same_as_rest< S, s0, s... >::value
> {};
template<typename S, S... s>
struct is_distinct : std::true_type {};
template<typename S, S s0, S... s>
struct is_distinct : std::integral_constant< bool,
std::is_distinct<S, s...>::value &&
first_not_same_as_rest< S, s0, s... >::value
> {};
Once you have that machinery (which requires C++11), we can do the following:
static_assert( is_distinct< E, A, B >::value, "duplicate values in E detected" );
and at compile time we will ensure that no two elements are equal.
This requires O(n) recursion depth and O(n^2) work by the compiler at compile time, so for extremely large enums this could cause problems. A O(lg(n)) depth and O(n lg(n)) work with a much larger constant factor can be done by sorting the list of elements first, but that is much, much more work.
With the enum reflection code proposed for C++1y-C++17, this will be doable without relisting the elements.
I didn't completely like any of the answers already posted here, but they gave me some ideas. The crucial technique is to rely on Ben Voight's answer of using a switch statement. If multiple cases in a switch share the same number, you'll get a compile error.
Most usefully to both myself and probably the original poster, this doesn't require any C++ features.
To clean things up, I used aaronps's answer at How can I avoid repeating myself when creating a C++ enum and a dependent data structure?
First, define this in some header someplace:
#define DEFINE_ENUM_VALUE(name, value) name=value,
#define CHECK_ENUM_VALUE(name, value) case name:
#define DEFINE_ENUM(enum_name, enum_values) \
typedef enum { enum_values(DEFINE_ENUM_VALUE) } enum_name;
#define CHECK_ENUM(enum_name, enum_values) \
void enum_name ## _test (void) { switch(0) { enum_values(CHECK_ENUM_VALUE); } }
Now, whenever you need to have an enumeration:
#define COLOR_VALUES(GEN) \
GEN(Red, 1) \
GEN(Green, 2) \
GEN(Blue, 2)
Finally, these lines are required to actually make the enumeration:
DEFINE_ENUM(Color, COLOR_VALUES)
CHECK_ENUM(Color, COLOR_VALUES)
DEFINE_ENUM makes the enum data type itself. CHECK_ENUM makes a test function that switches on all the enum values. The compiler will crash when compiling CHECK_ENUM if you have duplicates.
Here's a solution using X macro without Boost. First define the X macro and its helper macros. I'm using this solution to portably make 2 overloads for the X macro so that you can define the enum with or without an explicit value. If you're using GCC or Clang then it can be made shorter
#define COUNT_X_ARGS_IMPL2(_1, _2, count, ...) count
#define COUNT_X_ARGS_IMPL(args) COUNT_X_ARGS_IMPL2 args
#define COUNT_X_ARGS(...) COUNT_X_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
/* Pick the right X macro to invoke. */
#define X_CHOOSE_HELPER2(count) X##count
#define X_CHOOSE_HELPER1(count) X_CHOOSE_HELPER2(count)
#define X_CHOOSE_HELPER(count) X_CHOOSE_HELPER1(count)
/* The actual macro. */
#define X_GLUE(x, y) x y
#define X(...) X_GLUE(X_CHOOSE_HELPER(COUNT_X_ARGS(__VA_ARGS__)), (__VA_ARGS__))
Then define the macro and check it
#define BASE1_VAL (5)
#define BASE2_VAL (7)
// Enum values
#define MY_ENUM \
X(MsgFoo1A, BASE1_VAL) \
X(MsgFoo1B) \
X(MsgFoo1C) \
X(MsgFoo1D) \
X(MsgFoo1E) \
X(MsgFoo2A, BASE2_VAL) \
X(MsgFoo2B)
// Define the enum
#define X1(enum_name) enum_name,
#define X2(enum_name, enum_value) enum_name = enum_value,
enum foo
{
MY_ENUM
};
#undef X1
#undef X2
// Check duplicates
#define X1(enum_name) case enum_name: break;
#define X2(enum_name, enum_value) case enum_name: break;
static void check_enum_duplicate()
{
switch(0)
{
MY_ENUM
}
}
#undef X1
#undef X2
Use it
int main()
{
// Do something with the whole enum
#define X1(enum_name) printf("%s = %d\n", #enum_name, enum_name);
#define X2(enum_name, enum_value) printf("%s = %d\n", #enum_name, enum_value);
// Print the whole enum
MY_ENUM
#undef X1
#undef X2
}
I have a program that compares variables from two structs and sets a bit accordingly for a bitmap variable. I have to compare each variables of the struct. No. of variables in reality are more for each struct but for simplicity I took 3. I wanted to know if i can create a macro for comparing the variables and setting the bit in the bitmap accordingly.
#include<stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
int main()
{
struct num obj1;
struct num1 obj2;
int bitmap = 0;
if( obj1.a != obj2.d)
{
bitmap = bitmap | val1;
}
if (obj1.b != obj2.e)
bitmap = bitmap | val2;
printf("bitmap - %d",bitmap);
return 1;
}
can i declare a macro like...
#define CHECK(cond)
if (!(cond))
printf(" failed check at %x: %s",__LINE__, #cond);
//set the bit accordingly
#undef CHECK
With a modicum of care, you can do it fairly easily. You just need to identify what you're comparing and setting carefully, and pass them as macro parameters. Example usage:
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
This assumes that CHECK is defined something like:
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
You can lay the macro out however you like, of course; I'm not entirely happy with that, but it isn't too awful.
Demo Code
Compilation and test run:
$ gcc -Wall -Wextra -g -O3 -std=c99 xx.c -o xx && ./xx
failed check at 40: obj1.a != obj2.d
failed check at 42: obj1.c != obj2.f
bitmap - 5
$
Actual code:
#include <stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
int main(void)
{
struct num obj1 = { 1, 2, 3 };
struct num1 obj2 = { 2, 2, 4 };
int bitmap = 0;
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
CHECK(obj1.c, obj2.f, bitmap, val3);
printf("bitmap - %X\n", bitmap);
return 0;
}
Clearly, this code relies on you matching the right elements and bit numbers in the invocations of the CHECK macro.
It's possible to devise more complex schemes using offsetof() etc and initialized arrays describing the data structures, etc, but you'd end up with a more complex system and little benefit. In particular, the invocations can't reduce the parameter count much. You could assume 'bitmap' is the variable. You need to identify the two objects, so you'll specify 'obj1' and 'obj2'. Somewhere along the line, you need to identify which fields are being compared and the bit to set. That could be some single value (maybe the bit number), but you've still got 3 arguments (CHECK(obj1, obj2, valN) and the assumption about bitmap) or 4 arguments (CHECK(obj1, obj2, bitmap, valN) without the assumption about bitmap), but a lot of background complexity and probably a greater chance of getting it wrong. If you can tinker with the code so that you have a single type instead of two types, etc, then you can make life easier with the hypothetical system, but it is still simpler to handle things the way shown in the working code, I think.
I concur with gbulmer that I probably wouldn't do things this way, but you did state that you had reduced the sizes of the structures dramatically (for which, thanks!) and it would become more enticing as the number of fields increases (but I'd only write out the comparisons for one pair of structure types once, in a single function).
You could also revise the macro to:
#define CHECK(cond, bitmap, bit) do \
{ if (cond) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(cond)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
CHECK(obj1.a != obj2.d, bitmap, val1);
...
CHECK((strcmp(obj3.str1, obj4.str) != 0), bitmap, val6);
where the last line shows that this would allow you to choose arbitrary comparisons, even if they contain commas. Note the extra set of parentheses surrounding the call to strcmp()!
You should be able to do that except you need to use backslash for multi-line macros
#ifndef CHECK
#define CHECK(cond) \
if (!(cond)) { \
printf(" failed check at %x: %s",__LINE__, #cond); \
//set the bit accordingly
}
#endif /* CHECK */
If you want to get really fancy (and terse), you can use the concatenation operator. I also recommend changing your structures around a little bit to have different naming conventions, though without knowing what you're trying to do with it, it's hard to say. I also noticed in your bit field that you have one value that's 0; that won't tell you much when you try to look at that bit value. If you OR 0 into anything, it remains unchanged. Anyway, here's your program slightly re-written:
struct num {
int x1; // formerly a/d
int x2; // formerly b/e
int x3; // formerly c/f
};
enum type {
val1 = 1, // formerly 0
val2 = 2, // formerly 1
val3 = 4, // formerly 2
};
// CHECK uses the catenation operator (##) to construct obj1.x1, obj1.x2, etc.
#define CHECK(__num) {\
if( obj1.x##__num != obj2.x##__num )\
bitmap |= val##__num;\
}
void main( int argc, char** argv ) {
struct num obj1;
struct num obj2;
int bitmap = 0;
CHECK(1);
CHECK(2);
CHECK(3);
}
As a reasonable rule of thumb, when trying to do bit-arrays is C, there needs to be a number that can be used to index the bit.
You can either pass that bit number into the macro, or try to derive it.
Pretty much the only thing available at compile time or run time is the address of a field.
So you could use that.
There are a few questions to understand if it might work.
For your structs:
Are all the fields in the same order? I.e. you can compare c with f, and not c with e?
Do all of the corresponding fields have the same type
Is the condition just equality? Each macro will have the condition wired in, so each condition needs a new macro.
If the answer to all is yes, then you could use the address:
#define CHECK(s1, f1, s2, f2) do \
{ if ((&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2)) \
|| (s1.f1) != (s2.f2) \
{ printf("failed check at %d: ", #s1 "." #f1 "!=" #s1 "." #f1 "\n", \
__LINE__); \
(shared_bitmap) |= (1 << (&s1.f1-&s1)); // test failed \
} \
} while (0)
I'm not too clear on whether it is a bitmap for all comparisons, or one per struct pair. I've assumed it is a bit map for all.
There is quite a lot of checking to ensure you haven't broken 'the two rules':
(&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2))
If you are confident that the tests will be correct, without those constraints, just throw that part of the test away.
WARNING I have not compiled that code.
This becomes much simpler if the values are an array.
I probably wouldn't use it. It seems a bit too tricky to me :-)
I've written a program to probe the limits of a system's C time.h functions and dump them out in JSON. Then other things which depend on those functions can know their limits.
# system time.h limits, as JSON
{
"gmtime": {
"max": 2147483647,
"min": -2147483648
},
"localtime": {
"max": 2147483647,
"min": -2147483648
},
"mktime": {
"max": {
"tm_sec": 7,
"tm_min": 14,
"tm_hour": 19,
"tm_mday": 18,
"tm_mon": 0,
"tm_year": 138,
"tm_wday": 1,
"tm_yday": 17,
"tm_isdst": 0
},
"min": {
"tm_sec": 52,
"tm_min": 45,
"tm_hour": 12,
"tm_mday": 13,
"tm_mon": 11,
"tm_year": 1,
"tm_wday": 5,
"tm_yday": 346,
"tm_isdst": 0
}
}
}
gmtime() and localtime() are simple enough, they just take numbers, but mktime() takes a tm struct. I wrote a custom function to turn a tm struct into a JSON hash.
/* Dump a tm struct as a json fragment */
char * tm_as_json(const struct tm* date) {
char *date_json = malloc(sizeof(char) * 512);
#ifdef HAS_TM_TM_ZONE
char zone_json[32];
#endif
#ifdef HAS_TM_TM_GMTOFF
char gmtoff_json[32];
#endif
sprintf(date_json,
"\"tm_sec\": %d, \"tm_min\": %d, \"tm_hour\": %d, \"tm_mday\": %d, \"tm_mon\": %d, \"tm_year\": %d, \"tm_wday\": %d, \"tm_yday\": %d, \"tm_isdst\": %d",
date->tm_sec, date->tm_min, date->tm_hour, date->tm_mday,
date->tm_mon, date->tm_year, date->tm_wday, date->tm_yday, date->tm_isdst
);
#ifdef HAS_TM_TM_ZONE
sprintf(&zone_json, ", \"tm_zone\": %s", date->tm_zone);
strcat(date_json, zone_json);
#endif
#ifdef HAS_TM_TM_GMTOFF
sprintf(&gmtoff_json", \"tm_gmtoff\": %ld", date->tm_gmtoff);
strcat(date_json, gmtoff_json);
#endif
return date_json;
}
Is there a way to do this generically, for any given struct?
Note: C, not C++.
Not in C—at least in general. But if the C module is compiled with debug symbols, and the object module is available, you could parse that and discover everything about the structure. I bet there's a library for your system to assist with that.
Having come across the same issue, i wrote one myself. https://github.com/jamie-pate/jstruct . It's written to allow annotating existing c structures, then generate meta-data information based on the annotations. The library reads the metadata to import/export c structures to json strings and back. A python script takes care of parsing the annotated header and generating new headers and metadata initializers. The jstruct library uses https://github.com/json-c/json-c internally.
I have also noticed https://github.com/marel-keytech... but that was after writing the entire thing. (and info on that project's page is sparse)
There's no support yet for annotating a single struct from an existing system lib but you could wrap the tm struct in an annotated custom struct. (I think?)
Feel free to add features requests or even pull requests if you have ideas that would make the library more useful to you. One idea I had would be to add a way to embed that kind of read only struct inside an annotated wrapper with a #inline annotation: eg (currently unsupported but could be added)
//#json
struct my_time {
//#inline
struct tm tm;
}
Code:
struct my_time t;
mktime(&t.tm);
struct json_object *result = jstruct_export(t, my_time);
In the mean time you could do the same thing without #inline (since it hasn't been written yet) and just extract the tm property by hand with json_object_to_json_string(json_object_object_get(result, "tm"))
This won't quite give you what you're asking for, but it might help a little:
#define NAME_AND_INT(buf, obj, param) \
sprintf((buf), "\"%s\": %d, ", #param, (obj)->(param))
You could then iterate, e.g. something like (note: not tested; consider this pseudo-code):
char * tm_as_json(const struct tm* date) {
/* ... */
char buf[BUFSIZ]; /* or, use your date_json */
pos = buf; /* I note you use the equivalent of &buf -- that works too */
/* (not sure which is "better", but I've always left the & off
* things like that -- buf is essentially a pointer, it's just
* been allocated in a different way. At least that's how I
* think of it. */
pos += NAME_AND_INT(pos, date, tm_sec);
pos += NAME_AND_INT(pos, date, tm_min);
/* ... more like this ... */
/* strip trailing ", " (comma-space): */
pos-=2;
*pos = '\0';
/* ... */
}
You could similarly define NAME_AND_STRING, NAME_AND_LONG, etc. (for tm_zone and tm_gmtoff) as needed.
Again, it's not a generic solution, but it at least gets you a little closer, maybe.
Disclaimer: I'm the owner of the project https://github.com/tamask1s/zax-parser
With the help of the library, you can convert a C struct to JSON if you provide some information on your struct members which needs to be converted. There will be no need to include generated code in your project, but you will need a c++11 compiler in order to use it.
The lib is quite immature because I have implemented only the features I needed, but you may extend it, or you may use it as inspiration.
Example:
#define some_json_properties JSON_PROPERTY(x), JSON_PROPERTY(s)
struct some_class
{
int x = 9;
std::string s = "something";
ZAX_JSON_SERIALIZABLE(some_class, some_json_properties)
};
std::string some_json = some_obj;
---some_json's value:---
{"x":9, "s":"something"}
Nesting of objects is also possible, please check this example: https://tamask1s.github.io/zax-parser/index.html#Parsing_of_structures_with_fields_of_serializable_structures
Tom Christiansen once wrote pstruct/h2ph which is in perl CORE to parse .stabs info from the used compiler, and create readable info for all data structures.
C structs into JSON is trivial based on h2ph.
http://perl5.git.perl.org/perl.git/blob/HEAD:/utils/h2ph.PL
This macro does not do exactly what you want (generate JSON dump of C data), but I think it shows some possibility. You can dump content of any C data with a "p(...);" call.
I used gdb as external helper to make this work, but it is possible to implement one with libbfd. In that case, you can fully control your output - like generating JSON compatible output.
#ifndef PP_H
#define PP_H
/*
* Helper function (macro) for people who loves printf-debugging.
* This dumps content of any C data/structure/expression without prior
* knowledge of actual format. Works just like "p" or "pp" in Ruby.
*
* Usage:
* p(anyexpr);
*
* NOTE:
* - Program should be compiled with "-g" and preferrably, with "-O0".
*
* FIXME:
* - Would be better if this doesn't depend on external debugger to run.
* - Needs improvement on a way prevent variable from being optimized away.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
// Counts number of actual arguments.
#define COUNT_(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define COUNT(...) COUNT_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
// Dispatches macro call by number of actual arguments.
// Following is an example of actual macro expansion performed in case
// of 3 arguments:
//
// p(a, b, c)
// -> FUNC_N(p, COUNT(a, b, c), a, b, c)
// -> FUNC_N(p, 3, a, b, c)
// -> p_3(a, b, c)
//
// This means calling with simple "p(...)" is fine for any number of
// arguments, simulating "true" variadic macro.
#define CONCAT(name, count) name##count
#define FUNC_N(name, count, ...) CONCAT(name, count)(__VA_ARGS__)
// Forbids variable from being optimized out, so debugger can access it.
//
// FIXME:
// - Current implementation does not work with certain type of symbols
#define ENSURE(...) FUNC_N(ENSURE_, COUNT(__VA_ARGS__), __VA_ARGS__)
#define ENSURE_1(a) asm(""::"m"(a))
#define ENSURE_2(a, ...) do { ENSURE_1(a); ENSURE_1(__VA_ARGS__); } while (0)
#define ENSURE_3(a, ...) do { ENSURE_1(a); ENSURE_2(__VA_ARGS__); } while (0)
#define ENSURE_4(a, ...) do { ENSURE_1(a); ENSURE_3(__VA_ARGS__); } while (0)
#define ENSURE_5(a, ...) do { ENSURE_1(a); ENSURE_4(__VA_ARGS__); } while (0)
#define ENSURE_6(a, ...) do { ENSURE_1(a); ENSURE_5(__VA_ARGS__); } while (0)
#define ENSURE_7(a, ...) do { ENSURE_1(a); ENSURE_6(__VA_ARGS__); } while (0)
#define ENSURE_8(a, ...) do { ENSURE_1(a); ENSURE_7(__VA_ARGS__); } while (0)
// Dumps content of given symbol (uses external GDB for now)
//
// NOTE:
// - Should use libbfd instead of gdb? (but this adds complexity...)
#define PP_D(...) do { \
char *arg[] = { __VA_ARGS__, NULL }; \
char **argp = arg; \
char cmd[1024]; \
FILE *tmp = tmpfile(); \
fprintf(tmp, "attach %d\n", getpid()); \
fprintf(tmp, "frame 2\n"); \
while (*argp) \
fprintf(tmp, "p %s\n", *argp++); \
fprintf(tmp, "detach\n"); \
fflush(tmp); \
sprintf(cmd, "gdb -batch -x /proc/%d/fd/%d", \
getpid(), fileno(tmp)); \
system(cmd); \
fclose(tmp); \
} while (0)
#define PP(...) do { \
FUNC_N(PP_, COUNT(__VA_ARGS__), __VA_ARGS__); \
ENSURE(__VA_ARGS__); \
} while (0)
#define PP_1(a) do { PP_D(#a); } while (0)
#define PP_2(a,b) do { PP_D(#a,#b); } while (0)
#define PP_3(a,b,c) do { PP_D(#a,#b,#c); } while (0)
#define PP_4(a,b,c,d) do { PP_D(#a,#b,#c,#d); } while (0)
#define PP_5(a,b,c,d,e) do { PP_D(#a,#b,#c,#d,#e); } while (0)
#define PP_6(a,b,c,d,e,f) do { PP_D(#a,#b,#c,#d,#e,#f); } while (0)
#define PP_7(a,b,c,d,e,f,g) do { PP_D(#a,#b,#c,#d,#e,#f,#g); } while (0)
#define PP_8(a,b,c,d,e,f,g,h) do { PP_D(#a,#b,#c,#d,#e,#f,#g,#h); } while (0)
// Comment this out if you think this is too aggressive.
#define p PP
#endif
Indentation is lost in above paste, but you can grab the source from: https://github.com/tai/ruby-p-for-c