背景
在平时项目开发中,经常需要将事件或者ID转化为字符串。本文根据Mellanox驱动代码中的ib_event介绍介绍一种比较优雅的定义,判断的方法以及可以未来直接使用的代码。它的核心有点在于可以定义跳空的事件,以及直接使用字符串数组下标判空和越界的方法。
一般方法是定义事件类型和字符串,然后解析。
一般判断方法是 if event < EVENT_START && event > EVENT_END, return “unknown”
并且定义enum也需要指定start和end类似这种:
enum ib_event_type {
IB_EVENT_START,
IB_EVENT_CQ_ERR = IB_EVENT_START,
IB_EVENT_QP_FATAL, //最后一行也有,
IB_EVENT_END = IB_EVENT_QP_FATAL,
}
该方法需要定义start和end,或者需要动态的用第一个和最后一个,如果第一个和最后一个变化,还需要修改enum,是否有更优雅的一点方法?避免频繁修改,避免if判断?以及做到事件ID可以不连续?
事件字符串解析三部曲
答案是可以用三目运算符来判断evnet是否存在?甚至不用将event从0开始定义,最大event用事件字符串大小来确定(注意不是evnet大小)。并且判断用三目判断是否在其中,在其中用字符串数组取值,否则用指定的字符串。
当然三目运算的本质和if判断一样,最后编译到汇编几乎相同,都是条件判断。但是三目更加优雅。所以在以后很多场景可以用三目来替代if。尤其是双分支场景。
事件ID不连续的解析方法,是根据array的结构化初始化,不连续的跳空位置会自动初始化为0
三部曲定义:
# .h中定义事件和函数
enum ib_event_type {
IB_EVENT_CQ_ERR,
IB_EVENT_QP_FATAL, //最后一行也有,
}
const char *__attribute_const__ ib_event_msg(enum ib_event_type event);
# .c中定义事件字符串
static const char * const str_ib_events[] = {
[IB_EVENT_CQ_ERR] = "CQ error",
[IB_EVENT_QP_FATAL] = "QP fatal error",
}