命令模式。在命令模式里面,我们只需要维护一个命令列表就行了,而不需要关注解析函数本身。 先来看一个通讯协议相关的例子,数据帧定义如下:
帧长度 | 传感器类型 | 数据 |
---|---|---|
1字节 | 1字节 | n字节 |
传感器数据格式定义如下
传感器 | 类型号 | 数据格式 |
---|---|---|
温度传感器 | 1 | 整型数据(4字节) |
湿度传感器 | 2 | 整型数据(4字节) |
// 当心字节对齐的问题
typedef struct {
uint8_t head;
uint8_t cmd;
uint16_t length;
uint8_t data[1];
} package_t;
static void parse_temperature( uint8_t *buffer )
{
int value = *buffer;
printf( "temperature = %d\n", value );
}
static void parse_humidity( uint8_t *buffer )
{
int value = *buffer;
printf( "humidity = %d\n", value );
}
static void parse_illumination( uint8_t *buffer )
{
int value = *buffer;
printf( "illumination = %d\n", value );
}
typedef struct {
uint8_t cmd;
void ( * handle )( uint8_t *buffer );
} parse_handler;
static const parse_handler handlers[] = {
{0x01, parse_temperature},
{0x02, parse_humidity},
{0x03, parse_illumination},
{0xFF, NULL},
};
static uint8_t parse( uint8_t *buffer, uint16_t length )
{
package_t *frame = ( package_t * )buffer;
uint8_t tail = buffer[length - 1];
const parse_handler *entry;
if ( frame->head != 0xFF ) {
return 0;
}
for ( entry = handlers; entry->handle != NULL; ++entry ) {
if ( frame->cmd == entry->cmd ) {
entry->handle( frame->data );
break;
}
}
return 1;
}
int main( void )
{
uint8_t buffer[] = {0xFF, 0x01, 0x00, 0x05, 0x02};
parse( buffer, 5 );
uint8_t buffer_2[] = {0xFF, 0x02, 0x00, 0x05, 0x02};
parse( buffer_2, 5 );
uint8_t buffer_3[] = {0xFF, 0x03, 0x00, 0x05, 0x02};
parse( buffer_3, 5 );
}