From 3b841cc427adddeeb5b624d254587a45622d506d Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 29 Oct 2023 16:36:44 +0000 Subject: [PATCH] vg_msg api change --- vg_msg.h | 527 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 341 insertions(+), 186 deletions(-) diff --git a/vg_msg.h b/vg_msg.h index 791308e..f0c8d25 100644 --- a/vg_msg.h +++ b/vg_msg.h @@ -22,11 +22,11 @@ * Creating the data in code: * ----------------------------------------------------------------------------- * u8 data_buf[512]; - * vg_msg data = {0}; - * data.buf = data_buf; - * data.max = sizeof(data_buf); + * vg_msg data; + * vg_msg_init( &data, data_buf, 512 ); + * * vg_msg_wkvstr( &data, "kvstr", "someinfo" ); - * vg_msg_wkvint( &data, "kvint", i32 value=200 ); + * vg_msg_wkvu32( &data, "kvint", 200 ); * * vg_msg_frame( &data, "person" ); * vg_msg_wkvstr( &data, "name", "jeff" ); @@ -34,7 +34,7 @@ * vg_msg_end_frame( &data ); * * vg_msg_frame( &data, "building" ); - * vg_msg_wkvint( &data, "capacity", i32 value=1000 ); + * vg_msg_wkvu32( &data, "capacity", 1000 ); * vg_msg_end_frame( &data ); * * vg_msg_frame( &data, "person" ); @@ -57,9 +57,19 @@ * * // read data_buf and data_len * - * vg_msg data = {0}; - * data.buf = data_buf; - * data.len = data_len; + * vg_msg data; + * vg_msg_init( &data, data_buf, data_len ); + * + * + * Reading data + * ----------------------------------------------------------------------------- + * + * if( vg_msg_seekframe( &msg, "rows" ) ){ + * while( vg_msg_seekframe( &msg, NULL ) ){ + * vg_warn( "%s\n", vg_msg_readkvstr( &msg, "yedo" ) ); + * vg_msg_skip_frame( &msg ); + * } + * } * * Reading back the stream linearly * ----------------------------------------------------------------------------- @@ -71,28 +81,6 @@ * esle if( cmd.code == k_vg_msg_kvstring ) * printf( "string: %s\n", cmd.value._buf ); * } - * - * Reading back the stream as frames/nodes. this is obviously slower - * ----------------------------------------------------------------------------- - * - * vg_msg person = data - * while( vg_msg_seekframe( &person, "person", VG_MSG_NEXT ) ){ - * const char *name = vg_msg_seekkvstr(&person, "name", VG_MSG_NEXT); - * const char *country = vg_msg_seekkvstr(&person, "country", VG_MSG_FIRST); - * - * printf( "Guy '%s' is from '%s'\n", name, country ); - * vg_msg_skip_frame(&person); - * } - * - * 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_signed ) - * print( "building capacity: %d\n", capacity.value._i32 ); - * - * vg_msg_skip_frame( &building ); - * } - * */ enum vg_msg_code{ @@ -111,25 +99,45 @@ enum vg_msg_code{ /* masks */ k_vg_msg_array_count_bits = 0x3C, - k_vg_msg_size_bits = 0x03, - k_vg_msg_sized_type_bits = 0xC0, + k_vg_msg_type_size_bits = 0x03, + k_vg_msg_type_base_bits = 0xC0, + k_vg_msg_type_bits = k_vg_msg_type_base_bits|k_vg_msg_type_size_bits, - /* helpers */ + /* sizes */ k_vg_msg_8b = 0x00, k_vg_msg_16b = 0x01, k_vg_msg_32b = 0x02, k_vg_msg_64b = 0x03, + + /* common types */ + k_vg_msg_u8 = k_vg_msg_unsigned|k_vg_msg_8b, + k_vg_msg_u16 = k_vg_msg_unsigned|k_vg_msg_16b, + k_vg_msg_u32 = k_vg_msg_unsigned|k_vg_msg_32b, + k_vg_msg_u64 = k_vg_msg_unsigned|k_vg_msg_64b, + k_vg_msg_i8 = k_vg_msg_signed |k_vg_msg_8b, + k_vg_msg_i16 = k_vg_msg_signed |k_vg_msg_16b, + k_vg_msg_i32 = k_vg_msg_signed |k_vg_msg_32b, + k_vg_msg_i64 = k_vg_msg_signed |k_vg_msg_64b, + k_vg_msg_f32 = k_vg_msg_float |k_vg_msg_32b, + k_vg_msg_f64 = k_vg_msg_float |k_vg_msg_64b, + + k_vg_msg_v2f = k_vg_msg_float |k_vg_msg_32b | (1<<2), + k_vg_msg_v3f = k_vg_msg_float |k_vg_msg_32b | (2<<2), + k_vg_msg_v4f = k_vg_msg_float |k_vg_msg_32b | (3<<2) }; typedef struct vg_msg vg_msg; typedef struct vg_msg_cmd vg_msg_cmd; +typedef struct vg_msg_cursor vg_msg_cursor; struct vg_msg{ - u32 cur,len,max; + u32 max; u8 *buf; - u32 depth; /* reading */ - u32 rframe_depth, rframe_cur; + struct vg_msg_cursor { + u32 co, depth; + } + cur; enum vg_msg_error{ k_vg_msg_error_OK, @@ -148,32 +156,33 @@ struct vg_msg_cmd{ const void *value; u32 value_djb2; + + u32 len; /* set if binary type */ }; /* 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 ){ + if( msg->cur.co+len > msg->max ){ msg->error = k_vg_msg_error_overflow; return; } for( u32 i=0; ibuf[ msg->cur ++ ] = buf[i]; - msg->len ++; + msg->buf[ msg->cur.co ++ ] = buf[i]; } } /* 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->len ){ + if( msg->cur.co+len > msg->max ){ msg->error = k_vg_msg_error_overflow; return; } for( u32 i=0; ibuf[ msg->cur ++ ]; + buf[i] = msg->buf[ msg->cur.co ++ ]; } } @@ -191,10 +200,10 @@ static const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 ){ if( msg->error != k_vg_msg_error_OK ) return 0; u32 hash = 5381, c; - const char *str = (void *)(&msg->buf[ msg->cur ]); + const char *str = (void *)(&msg->buf[ msg->cur.co ]); - while( (c = msg->buf[ msg->cur ++ ]) ){ - if( msg->cur >= msg->max ){ + while( (c = msg->buf[ msg->cur.co ++ ]) ){ + if( msg->cur.co >= msg->max ){ msg->error = k_vg_msg_error_overflow; return 0; } @@ -209,40 +218,19 @@ static const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 ){ static void vg_msg_frame( vg_msg *msg, const char *name ){ if( msg->error != k_vg_msg_error_OK ) return; - msg->depth ++; + msg->cur.depth ++; 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; - if( !msg->depth ){ + if( !msg->cur.depth ){ msg->error = k_vg_msg_error_unbalanced; return; } - msg->depth --; + msg->cur.depth --; vg_msg_wbuf( msg, (u8[]){ k_vg_msg_endframe }, 1 ); } @@ -261,11 +249,17 @@ static void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len ){ vg_msg_wbuf( msg, bin, len ); } +static u32 vg_msg_cmd_array_count( u8 code ){ + return ((code & k_vg_msg_array_count_bits)>>2) + 1; +} + +static u32 vg_msg_cmd_type_size( u8 code ){ + return 0x1 << (code & k_vg_msg_type_size_bits); +} + /* 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)>>2) + 1; - return size * count; +static u32 vg_msg_cmd_bytecount( u8 code ){ + return vg_msg_cmd_array_count( code ) * vg_msg_cmd_type_size( code ); } /* write a sized type */ @@ -275,15 +269,39 @@ static void vg_msg_wkvnum( vg_msg *msg, const char *key, vg_msg_wbuf( msg, &code, 1 ); vg_msg_wstr( msg, key ); - vg_msg_wbuf( msg, data, vg_msg_sized_bytecount(code) ); + vg_msg_wbuf( msg, data, vg_msg_cmd_bytecount(code) ); +} + +#define _WRITE_KV_INTG_HELPER( TYPE ) \ +static void vg_msg_wkv##TYPE( vg_msg *msg, const char *key, TYPE v ){ \ + vg_msg_wkvnum( msg, key, k_vg_msg_##TYPE, 1, &v ); \ } -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 ); +#define _WRITE_KV_VEC_HELPER( TYPE ) \ +static void vg_msg_wkv##TYPE( vg_msg *msg, const char *key, TYPE v ){ \ + vg_msg_wkvnum( msg, key, k_vg_msg_##TYPE, 1, v ); \ } -static void vg_msg_wkvu64( vg_msg *msg, const char *key, u64 value ){ - vg_msg_wkvnum( msg, key, k_vg_msg_unsigned|k_vg_msg_64b, 1, &value ); +_WRITE_KV_INTG_HELPER( u8 ) +_WRITE_KV_INTG_HELPER( u16 ) +_WRITE_KV_INTG_HELPER( u32 ) +_WRITE_KV_INTG_HELPER( u64 ) +_WRITE_KV_INTG_HELPER( i8 ) +_WRITE_KV_INTG_HELPER( i16 ) +_WRITE_KV_INTG_HELPER( i32 ) +_WRITE_KV_INTG_HELPER( i64 ) +_WRITE_KV_INTG_HELPER( f32 ) +_WRITE_KV_INTG_HELPER( f64 ) +_WRITE_KV_VEC_HELPER( v2f ) +_WRITE_KV_VEC_HELPER( v3f ) +_WRITE_KV_VEC_HELPER( v4f ) + +static void vg_msg_init( vg_msg *msg, u8 *buffer, u32 len ){ + msg->buf = buffer; + msg->cur.co = 0; + msg->cur.depth = 0; + msg->error = k_vg_msg_error_OK; + msg->max = len; } /* @@ -310,55 +328,57 @@ static int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd ){ if( cmd->code == k_vg_msg_frame ){ cmd->key = vg_msg_rstr( msg, &cmd->key_djb2 ); - msg->depth ++; + msg->cur.depth ++; } else if( cmd->code == k_vg_msg_endframe ){ - if( !msg->depth ){ + if( !msg->cur.depth ){ msg->error = k_vg_msg_error_unbalanced; return 0; } - msg->depth --; + msg->cur.depth --; } else if( cmd->code >= k_vg_msg_kv ){ cmd->key = vg_msg_rstr( msg, &cmd->key_djb2 ); cmd->value_djb2 = 0; - 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; + if( cmd->code & k_vg_msg_type_base_bits ){ + u32 bytes = vg_msg_cmd_bytecount( cmd->code ); + cmd->value = &msg->buf[ msg->cur.co ]; + msg->cur.co += bytes; } else if( cmd->code == k_vg_msg_kvstring ){ cmd->value = vg_msg_rstr( msg, &cmd->value_djb2 ); } else if( cmd->code == k_vg_msg_kvbin ){ - u32 len; - vg_msg_rbuf( msg, (u8 *)(&len), 4 ); - if( msg->error != k_vg_msg_error_OK ) return 0; - cmd->value = &msg->buf[ msg->cur ]; - msg->cur += len; + vg_msg_rbuf( msg, (u8 *)(&cmd->len), 4 ); + if( msg->error != k_vg_msg_error_OK ) + return 0; + cmd->value = &msg->buf[ msg->cur.co ]; + msg->cur.co += cmd->len; } else msg->error = k_vg_msg_error_unhandled_cmd; - if( msg->cur > msg->max ) + if( msg->cur.co > msg->max ) msg->error = k_vg_msg_error_overflow; } else msg->error = k_vg_msg_error_unhandled_cmd; - if( msg->error != k_vg_msg_error_OK ) return 0; - else return 1; + if( msg->error != k_vg_msg_error_OK ) + return 0; + else + return 1; } /* move through the frame(and subframes) until we fall out of it */ static int vg_msg_skip_frame( vg_msg *msg ){ vg_msg_cmd cmd; - u32 depth = msg->depth-1; - while( vg_msg_next( msg, &cmd ) ){ - if( msg->depth == depth ) return 1; - } + u32 start_depth = msg->cur.depth; + while( vg_msg_next( msg, &cmd ) ) + if( msg->cur.depth < start_depth ) + return 1; return 0; } @@ -367,135 +387,270 @@ static int vg_msg_skip_frame( vg_msg *msg ){ * ----------------------------------------------------------------------------- */ -enum vg_msg_dir{ - k_vg_msg_first=0, /* reset the frame pointer and find the first thing */ - k_vg_msg_next=1 /* get next item in the stream, wont find behind cursor */ -}; - -/* reset frame pointer and depth to the start of the frame set by seekframe */ -static void vg_msg_framereset( vg_msg *frame ){ - frame->cur = frame->rframe_cur; - frame->depth = frame->rframe_depth; -} - -/* moves to a frame, and sets the base frame in msg if it finds it */ -static int vg_msg_seekframe( vg_msg *msg, const char *name, - enum vg_msg_dir dir ) -{ - if( dir == k_vg_msg_first ) vg_msg_framereset( msg ); - +/* moves to a frame, + * returns 0 if drops out of scope or ends. + */ +static int vg_msg_seekframe( vg_msg *msg, const char *name ){ + vg_msg_cursor orig = msg->cur; vg_msg_cmd cmd; while( vg_msg_next( msg, &cmd ) ){ - if( msg->depth < msg->rframe_depth ){ - vg_msg_framereset(msg); + if( msg->cur.depth < orig.depth ){ + msg->cur = orig; return 0; } - if( msg->depth != msg->rframe_depth+1 ) continue; - if( cmd.code == k_vg_msg_frame ){ - if( !name || VG_STRDJB2_EQ( name, cmd.key, cmd.key_djb2 ) ){ - msg->rframe_cur = msg->cur; - msg->rframe_depth = msg->depth; + if( msg->cur.depth != orig.depth+1 ) + continue; + if( cmd.code == k_vg_msg_frame ) + if( !name || VG_STRDJB2_EQ( name, cmd.key, cmd.key_djb2 ) ) return 1; - } - } } + msg->cur = orig; return 0; } -/* move to the kv named key, doesnt matter what type */ -static vg_msg_cmd vg_msg_seekkv( vg_msg *msg, const char *key, - enum vg_msg_dir dir ) -{ - if( dir == k_vg_msg_first ) vg_msg_framereset( msg ); - - vg_msg_cmd kv; - kv.code = k_vg_msg_end; - kv.key = ""; - kv.key_djb2 = 0; - kv.value = NULL; - kv.value_djb2 = 0; +/* + * Convert any type integral type to u64 + */ +static u64 vg_msg_cast_to_u64( const void *src, u8 src_base, u8 src_size ){ + if( src_base == k_vg_msg_float ){ + if( src_size == 4 ) return (u64)(*((f32*)src)); + else if( src_size == 8 ) return (u64)(*((f64*)src)); + else return 0; + } + else { + u64 a = 0; + memcpy( &a, src, src_size ); + return a; + } +} - vg_msg_cmd cmd; - while( vg_msg_next( msg, &cmd ) ){ - if( msg->depth < msg->rframe_depth ){ - vg_msg_framereset(msg); - return kv; - } - if( msg->depth > msg->rframe_depth ) continue; - if( cmd.code > k_vg_msg_kv ) - if( VG_STRDJB2_EQ( key, cmd.key, cmd.key_djb2 ) ) - return cmd; +/* + * Convert any integral type to i64 + */ +static i64 vg_msg_cast_to_i64( const void *src, u8 src_base, u8 src_size ){ + if( src_base == k_vg_msg_float ){ + if( src_size == 4 ) return (i64)(*((f32*)src)); + else if( src_size == 8 ) return (i64)(*((f64*)src)); + else return 0; } + else { + u64 a = 0; + memcpy( &a, src, src_size ); + + if( (src_base == k_vg_msg_signed) && (src_size != 8) ){ + /* extend sign bit */ + u64 sign_bit = 0x1llu << ((src_size*8)-1); + if( a & sign_bit ) + a |= (0xffffffffffffffffllu << (64-__builtin_clzll( a ))); + } - return kv; + return *((i64*)&a); + } } -/* helper for reading string kvs. returns NULL if not found */ -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_kvstring ) return cmd.value; - else return NULL; +/* + * Convert any integral type to f64 + */ +static f64 vg_msg_cast_to_f64( const void *src, u8 src_base, u8 src_size ){ + if( src_base == k_vg_msg_float ){ + if( src_size == 4 ) return (f64)(*((f32*)src)); + else if( src_size == 8 ) return *((f64*)src); + else return 0.0; + } + else + return (f64)vg_msg_cast_to_i64( src, src_base, src_size ); } -static u64 vg_msg_read_as_u64( vg_msg_cmd *cmd ){ - u8 sized_type = cmd->code & k_vg_msg_sized_type_bits; - - u64 result = 0x00; - u8 *dst = (void *)(&result); - const u8 *src = cmd->value; +/* + * Convert any full integral type code to another + * Passing in non-integral codes is undefined + */ +static void vg_msg_cast( const void *src, u8 src_code, void *dst, u8 dst_code ){ + if( src_code == dst_code ){ + memcpy( dst, src, vg_msg_cmd_bytecount( src_code ) ); + } + else { + u32 src_n = vg_msg_cmd_array_count( src_code ), + dst_n = vg_msg_cmd_array_count( dst_code ), + src_s = vg_msg_cmd_type_size( src_code ), + dst_s = vg_msg_cmd_type_size( dst_code ), + src_b = src_code & k_vg_msg_type_base_bits, + dst_b = dst_code & k_vg_msg_type_base_bits; + + memset( dst, 0, dst_s * dst_n ); + + for( u32 i=0; icode ); - if( bytes > 8 ) bytes = 8; - for( u32 i=0; icur; + while( vg_msg_next( msg, cmd ) ){ + if( msg->cur.depth < orig.depth ){ + msg->cur = orig; + return 0; + } + if( msg->cur.depth > orig.depth ) + continue; + if( cmd->code > k_vg_msg_kv ){ + if( VG_STRDJB2_EQ( key, cmd->key, cmd->key_djb2 ) ){ + msg->cur = orig; + return 1; + } + } } - return result; + msg->cur = orig; + return 0; } -static void -vg_msg_convert_num( vg_msg_cmd *cmd, u8 type, u32 count, void *result ){ - u8 code = type | ((count-1)<<2); - if( code != cmd->code ) return; +/* + * Read a integral KV out to dst, and perform conversion if needed + * dst is always defined, if its not found its set to 0 + */ +static int vg_msg_getkvintg( vg_msg *msg, const char *key, u8 type, void *dst ){ + vg_msg_cmd cmd; + if( vg_msg_getkvcmd( msg, key, &cmd ) ){ + vg_msg_cast( cmd.value, cmd.code, dst, type ); + return 1; + } + else { + memset( dst, 0, vg_msg_cmd_bytecount(type) ); + return 0; + } +} - const u8 *src = cmd->value; - u8 *dst = result; +/* helper for reading string kvs. returns NULL if not found */ +static const char *vg_msg_getkvstr( vg_msg *msg, const char *key ){ + vg_msg_cmd cmd; + if( vg_msg_getkvcmd( msg, key, &cmd ) ) + return cmd.value; + else + return NULL; +} - u32 bytes = vg_msg_sized_bytecount( cmd->code ); - for( u32 i=0; ierror != k_vg_msg_error_OK ){ + printf( "Message contains errors\n" ); + return; + } + + vg_msg b; + vg_msg_init( &b, msg->buf, len ); vg_msg_cmd cmd; while( vg_msg_next( &b, &cmd ) ){ if( cmd.code == k_vg_msg_frame ){ - for( u32 i=0; i (%u bytes)\n", cmd.key, cmd.len ); + else { + u32 base = cmd.code & k_vg_msg_type_base_bits, + count = vg_msg_cmd_array_count( cmd.code ), + size = vg_msg_cmd_type_size( cmd.code ); + + printf( "'%s': ", cmd.key ); + + if( count > 1 ) printf( "'{' " ); + + for( u32 i=0; i 1 ) printf( "'}'" ); + printf( "\n" ); } - else - printf( "'%s'[%u]: \n", cmd.key, cmd.key_djb2 ); } } } -- 2.25.1