From 27aeb14e8533349bf7b09a305b9ee775c42eb451 Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 11 Jun 2023 17:53:41 +0100 Subject: [PATCH] refine vg_msg slightly --- vg_msg.h | 276 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 176 insertions(+), 100 deletions(-) diff --git a/vg_msg.h b/vg_msg.h index 83bc086..0aef31e 100644 --- a/vg_msg.h +++ b/vg_msg.h @@ -22,8 +22,9 @@ * Creating the data in code: * ----------------------------------------------------------------------------- * u8 data_buf[512]; - * vg_msg data; - * vg_msg_init( &data, data_buf, 512 ); + * vg_msg data = {0}; + * data.buf = data_buf; + * data.max = sizeof(data_buf); * vg_msg_wkvstr( &data, "kvstr", "someinfo" ); * vg_msg_wkvint( &data, "kvint", i32 value=200 ); * @@ -53,18 +54,21 @@ * * u8 data_buf[512]; * u32 data_len; + * * // read data_buf and data_len - * vg_msg data; - * vg_msg_init( &data, data_buf, data_len ); + * + * vg_msg data = {0}; + * data.buf = data_buf; + * data.len = data_len; * * Reading back the stream linearly * ----------------------------------------------------------------------------- * * vg_msg_cmd cmd; * while( vg_msg_next( &data, &cmd ) ){ - * if( cmd.code == k_vg_msg_code_frame ) printf( "{" ); - * else if( cmd.code == k_vg_msg_code_endframe ) printf( "}" ); - * esle if( cmd.code == k_vg_msg_code_kvstring ) + * if( cmd.code == k_vg_msg_frame ) printf( "{" ); + * else if( cmd.code == k_vg_msg_endframe ) printf( "}" ); + * esle if( cmd.code == k_vg_msg_kvstring ) * printf( "string: %s\n", cmd.value._buf ); * } * @@ -83,7 +87,7 @@ * vg_msg building = root; * if( vg_msg_seekframe( &building, "building", VG_MSG_FIRST ) ){ * vg_msg_cmd capacity = vg_msg_seekkv(&building, "capacity", VG_MSG_FIRST); - * if( capacity.code & k_vg_msg_code_signed ) + * if( capacity.code & k_vg_msg_signed ) * print( "building capacity: %d\n", capacity.value._i32 ); * * vg_msg_skip_frame( &building ); @@ -92,22 +96,35 @@ */ enum vg_msg_code{ - k_vg_msg_code_end = 0, - k_vg_msg_code_frame = 1, - k_vg_msg_code_endframe = 2, - k_vg_msg_code_kv = 10, - k_vg_msg_code_kvstring = 11, - k_vg_msg_code_kvbin = 12, - k_vg_msg_code_signed = 0x80, /* byte sizes stored in lower 4 bits */ - k_vg_msg_code_unsigned = 0x40, - k_vg_msg_code_float = 0x20, - k_vg_msg_code_integer = k_vg_msg_code_signed|k_vg_msg_code_unsigned + /* low types */ + k_vg_msg_end = 0, + k_vg_msg_frame = 1, + k_vg_msg_endframe = 2, + k_vg_msg_kv = 10, + k_vg_msg_kvstring = 11, + k_vg_msg_kvbin = 12, + + /* variable sized types */ + k_vg_msg_float = 0x40, + k_vg_msg_unsigned = 0x80, + k_vg_msg_signed = 0xC0, + + /* masks */ + k_vg_msg_array_count_bits = 0x3C, + k_vg_msg_size_bits = 0x03, + k_vg_msg_sized_type_bits = 0xC0, + + /* helpers */ + k_vg_msg_8b = 0x00, + k_vg_msg_16b = 0x01, + k_vg_msg_32b = 0x02, + k_vg_msg_64b = 0x04, }; typedef struct vg_msg vg_msg; typedef struct vg_msg_cmd vg_msg_cmd; struct vg_msg{ - u32 cur,max; + u32 cur,len,max; u8 *buf; u32 depth; @@ -129,36 +146,34 @@ struct vg_msg_cmd{ const char *key; u32 key_djb2; - union{ const void *_buf; - u8 _u8; i8 _i8; - u16 _u16; i16 _i16; - u32 _u32; i32 _i32; f32 _f32; - u64 _u64; i64 _i64; f64 _f64; - } value; + const void *value; u32 value_djb2; }; -/* generic stream reset */ -static void vg_msg_init( vg_msg *msg, u8 *buf, u32 max ){ - msg->cur = 0; - msg->max = max; - msg->buf = buf; - msg->depth = 0; - msg->error = k_vg_msg_error_OK; - msg->rframe_depth = 0; - msg->rframe_cur = 0; +/* write a buffer from msg, rang checked. */ +static void vg_msg_wbuf( vg_msg *msg, u8 *buf, u32 len ){ + if( msg->error != k_vg_msg_error_OK ) return; + if( msg->cur+len > msg->max ){ + msg->error = k_vg_msg_error_overflow; + return; + } + + for( u32 i=0; ibuf[ msg->cur ++ ] = buf[i]; + msg->len ++; + } } -/* write or read a buffer from msg, rang checked. */ -static void vg_msg_exchbuf( vg_msg *msg, int write, u8 *buf, u32 len ){ +/* read a buffer from msg, rang checked. */ +static void vg_msg_rbuf( vg_msg *msg, u8 *buf, u32 len ){ if( msg->error != k_vg_msg_error_OK ) return; - if( msg->cur+len > msg->max ){ + if( msg->cur+len > msg->len ){ msg->error = k_vg_msg_error_overflow; return; } + for( u32 i=0; ibuf[ msg->cur ++ ] = buf[i]; - else buf[i] = msg->buf[ msg->cur ++ ]; + buf[i] = msg->buf[ msg->cur ++ ]; } } @@ -166,7 +181,7 @@ static void vg_msg_exchbuf( vg_msg *msg, int write, u8 *buf, u32 len ){ static void vg_msg_wstr( vg_msg *msg, const char *str ){ if( msg->error != k_vg_msg_error_OK ) return; for( u32 i=0;; i++ ){ - vg_msg_exchbuf( msg, 1, (u8[]){ str[i] }, 1 ); + vg_msg_wbuf( msg, (u8[]){ str[i] }, 1 ); if( !str[i] ) break; } } @@ -195,10 +210,31 @@ static void vg_msg_frame( vg_msg *msg, const char *name ){ if( msg->error != k_vg_msg_error_OK ) return; msg->depth ++; - vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_frame }, 1 ); + vg_msg_wbuf( msg, (u8[]){ k_vg_msg_frame }, 1 ); vg_msg_wstr( msg, name ); } +/* shift right side of cursor by len */ +static void vg_msg_makeroom( vg_msg *msg, u32 len ){ + if( msg->error != k_vg_msg_error_OK ) return; + if( msg->len + len > msg->max ){ + msg->error = k_vg_msg_error_overflow; + return; + } + u32 i = msg->len-msg->cur; + while( i --> 0 ){ + msg->buf[ msg->cur+len+i ] = msg->buf[ msg->cur+i ]; + } + msg->len += len; +} + +/* paste data into msg, at the cursor location */ +static void vg_msg_insert( vg_msg *msg, vg_msg *data ){ + vg_msg_makeroom( msg, data->len ); + vg_msg_wbuf( msg, data->buf, data->len ); + msg->depth += data->depth; +} + /* end frame in message stream */ static void vg_msg_end_frame( vg_msg *msg ){ if( msg->error != k_vg_msg_error_OK ) return; @@ -207,54 +243,44 @@ static void vg_msg_end_frame( vg_msg *msg ){ return; } msg->depth --; - vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_endframe }, 1 ); + vg_msg_wbuf( msg, (u8[]){ k_vg_msg_endframe }, 1 ); } /* write a KV string to stream */ static void vg_msg_wkvstr( vg_msg *msg, const char *key, const char *value ){ - vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_kvstring }, 1 ); + vg_msg_wbuf( msg, (u8[]){ k_vg_msg_kvstring }, 1 ); vg_msg_wstr( msg, key ); vg_msg_wstr( msg, value ); } /* write a binary block to stream */ static void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len ){ - vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_kvbin }, 1 ); + vg_msg_wbuf( msg, (u8[]){ k_vg_msg_kvbin }, 1 ); vg_msg_wstr( msg, key ); - vg_msg_exchbuf( msg, 1, (u8 *)(&len), 4 ); - vg_msg_exchbuf( msg, 1, bin, len ); + vg_msg_wbuf( msg, (u8 *)(&len), 4 ); + vg_msg_wbuf( msg, bin, len ); } -/* write a generic sized kv */ -static void vg__msg_wkvgen( vg_msg *msg, const char *key, - u8 basecode, void *value, u32 size ){ - u8 code = basecode | size; - vg_msg_exchbuf( msg, 1, &code, 1 ); - vg_msg_wstr( msg, key ); - vg_msg_exchbuf( msg, 1, value, size ); +/* get the byte count of a sized code */ +static u32 vg_msg_sized_bytecount( u8 code ){ + u32 size = 0x1 << (code & k_vg_msg_size_bits), + count = (code & k_vg_msg_array_count_bits) + 1; + return size * count; } -/* - * macros to write sized integers and floats - * - * you use them like: - * vg_msg_wkvint( &msg, "key", u32 value=32 ); - * - * this will write a 32 bit unsigned int to the stream - */ +/* write a sized type */ +static void vg_msg_wkvnum( vg_msg *msg, const char *key, + u8 type, u8 count, void *data ){ + u8 code = type | ((count-1)<<2); -#define vg_msg_wkvint( MSGPTR, KEY, DECL ){ \ - DECL; \ - vg__msg_wkvgen(MSGPTR, KEY, k_vg_msg_code_signed, &value, sizeof(value));\ - } -#define vg_msg_wkvuint( MSGPTR, KEY, DECL ){ \ - DECL; \ - vg__msg_wkvgen(MSGPTR, KEY, k_vg_msg_code_unsigned, &value, sizeof(value));\ - } -#define vg_msg_wkvfloat( MSGPTR, KEY, DECL ){ \ - DECL; \ - vg__msg_wkvgen(MSGPTR, KEY, k_vg_msg_code_float, &value, sizeof(value));\ - } + vg_msg_wbuf( msg, &code, 1 ); + vg_msg_wstr( msg, key ); + vg_msg_wbuf( msg, data, vg_msg_sized_bytecount(code) ); +} + +static void vg_msg_wkvu32( vg_msg *msg, const char *key, u32 value ){ + vg_msg_wkvnum( msg, key, k_vg_msg_unsigned|k_vg_msg_32b, 1, &value ); +} /* * The stream reading interface @@ -265,50 +291,57 @@ static void vg__msg_wkvgen( vg_msg *msg, const char *key, * create an error if it runs of the end of the stream. every possible command * must be handled in this function */ static int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd ){ - vg_msg_exchbuf( msg, 0, &cmd->code, 1 ); + vg_msg_rbuf( msg, &cmd->code, 1 ); + +#ifdef VG_MSG_V1_SUPPORT + /* |sized| |count-1| |shift| + * 0 1 0 0 0 1 0 0 0x44 (1 byte, float[2]. So, never used anyway) + * converts to + * 1 0 0 0 0 0 1 0 0x82 + */ + if( cmd->code == 0x44 ) cmd->code = 0x82; +#endif + if( msg->error != k_vg_msg_error_OK ) return 0; - if( cmd->code == k_vg_msg_code_frame ){ + if( cmd->code == k_vg_msg_frame ){ cmd->key = vg_msg_rstr( msg, &cmd->key_djb2 ); msg->depth ++; } - else if( cmd->code == k_vg_msg_code_endframe ){ + else if( cmd->code == k_vg_msg_endframe ){ if( !msg->depth ){ msg->error = k_vg_msg_error_unbalanced; return 0; } msg->depth --; } - else if( cmd->code >= k_vg_msg_code_kv ){ + else if( cmd->code >= k_vg_msg_kv ){ cmd->key = vg_msg_rstr( msg, &cmd->key_djb2 ); cmd->value_djb2 = 0; - cmd->value._u64 = 0; - if( cmd->code & (k_vg_msg_code_float|k_vg_msg_code_unsigned| - k_vg_msg_code_signed )){ - u8 len = cmd->code & 0xf; - vg_msg_exchbuf( msg, 0, (u8 *)(&cmd->value._u64), len ); + if( cmd->code & k_vg_msg_sized_type_bits ){ + u32 bytes = vg_msg_sized_bytecount( cmd->code ); + cmd->value = &msg->buf[ msg->cur ]; + msg->cur += bytes; } - else if( cmd->code == k_vg_msg_code_kvstring ){ - cmd->value._buf = vg_msg_rstr( msg, &cmd->value_djb2 ); + else if( cmd->code == k_vg_msg_kvstring ){ + cmd->value = vg_msg_rstr( msg, &cmd->value_djb2 ); } - else if( cmd->code == k_vg_msg_code_kvbin ){ + else if( cmd->code == k_vg_msg_kvbin ){ u32 len; - vg_msg_exchbuf( msg, 0, (u8 *)(&len), 4 ); + vg_msg_rbuf( msg, (u8 *)(&len), 4 ); if( msg->error != k_vg_msg_error_OK ) return 0; - cmd->value._buf = &msg->buf[ msg->cur ]; + cmd->value = &msg->buf[ msg->cur ]; msg->cur += len; - if( msg->cur > msg->max ){ - msg->error = k_vg_msg_error_overflow; - } } - else{ + else msg->error = k_vg_msg_error_unhandled_cmd; - } + + if( msg->cur > msg->max ) + msg->error = k_vg_msg_error_overflow; } - else{ + else msg->error = k_vg_msg_error_unhandled_cmd; - } if( msg->error != k_vg_msg_error_OK ) return 0; else return 1; @@ -354,7 +387,7 @@ static int vg_msg_seekframe( vg_msg *msg, const char *name, return 0; } if( msg->depth != msg->rframe_depth+1 ) continue; - if( cmd.code == k_vg_msg_code_frame ){ + if( cmd.code == k_vg_msg_frame ){ if( VG_STRDJB2_EQ( name, cmd.key, cmd.key_djb2 ) ){ msg->rframe_cur = msg->cur; msg->rframe_depth = msg->depth; @@ -373,11 +406,11 @@ static vg_msg_cmd vg_msg_seekkv( vg_msg *msg, const char *key, if( dir == k_vg_msg_first ) vg_msg_framereset( msg ); vg_msg_cmd kv; - kv.code = k_vg_msg_code_end; + kv.code = k_vg_msg_end; kv.key = ""; kv.key_djb2 = 0; - kv.value._u64 = 0; - kv.key_djb2 = 0; + kv.value = NULL; + kv.value_djb2 = 0; vg_msg_cmd cmd; while( vg_msg_next( msg, &cmd ) ){ @@ -386,7 +419,7 @@ static vg_msg_cmd vg_msg_seekkv( vg_msg *msg, const char *key, return kv; } if( msg->depth > msg->rframe_depth ) continue; - if( cmd.code > k_vg_msg_code_kv ) + if( cmd.code > k_vg_msg_kv ) if( VG_STRDJB2_EQ( key, cmd.key, cmd.key_djb2 ) ) return cmd; } @@ -399,9 +432,52 @@ static const char *vg_msg_seekkvstr( vg_msg *msg, const char *key, enum vg_msg_dir dir ) { vg_msg_cmd cmd = vg_msg_seekkv( msg, key, dir ); - if( cmd.code == k_vg_msg_code_kvstring ) return cmd.value._buf; + if( cmd.code == k_vg_msg_kvstring ) return cmd.value; else return NULL; } +static u32 vg_msg_seekkvu32( vg_msg *msg, const char *key, enum vg_msg_dir dir ) +{ + vg_msg_cmd cmd = vg_msg_seekkv( msg, key, dir ); + u8 sized_type = cmd.code & k_vg_msg_sized_type_bits; + + u32 result = 0x00; + u8 *dst = (void *)(&result); + const u8 *src = cmd.value; + + if( (sized_type == k_vg_msg_unsigned) || (sized_type == k_vg_msg_signed) ){ + u32 bytes = vg_msg_sized_bytecount( cmd.code ); + if( bytes > 4 ) bytes = 4; + for( u32 i=0; i\n", cmd.key, cmd.key_djb2 ); + } + } +} #endif /* VG_MSG_H */ -- 2.25.1