X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_msg.h;h=b5fb4a482bf991ef4624b65ab93b89be33da51a6;hb=HEAD;hp=cc38e859cc0a9b34eb217e9c88da2af3d24ded87;hpb=bd0220bf8c44fc5d368e6edf4d0769bbcd5eba5d;p=vg.git diff --git a/vg_msg.h b/vg_msg.h index cc38e85..0b13024 100644 --- a/vg_msg.h +++ b/vg_msg.h @@ -1,27 +1,144 @@ -#ifndef VG_MSG_H -#define VG_MSG_H -#include "vg_stdint.h" +#pragma once +/* + * Example data: + * kvstr "someinfo" + * kvint 200 + * frame "person"{ + * name "jeff" + * country "england" + * } + * frame "building"{ + * capacity 1000 + * } + * frame "person"{ + * country "wales" + * name "micheal" + * } + * + * Creating the data in code: + * ----------------------------------------------------------------------------- + * u8 data_buf[512]; + * vg_msg data; + * vg_msg_init( &data, data_buf, 512 ); + * + * vg_msg_wkvstr( &data, "kvstr", "someinfo" ); + * vg_msg_wkvu32( &data, "kvint", 200 ); + * + * vg_msg_frame( &data, "person" ); + * vg_msg_wkvstr( &data, "name", "jeff" ); + * vg_msg_wkvstr( &data, "country", "england" ); + * vg_msg_end_frame( &data ); + * + * vg_msg_frame( &data, "building" ); + * vg_msg_wkvu32( &data, "capacity", 1000 ); + * vg_msg_end_frame( &data ); + * + * vg_msg_frame( &data, "person" ); + * vg_msg_wkvstr( &data, "country", "wales" ); + * vg_msg_wkvstr( &data, "name", "micheal" ); + * vg_msg_end_frame( &data ); + * + * Saving the data out + * ----------------------------------------------------------------------------- + * + * if( data.error == k_vg_msg_error_OK ){ + * // write data_buf, for length data.cur + * } + * + * Load the data + * ----------------------------------------------------------------------------- + * + * u8 data_buf[512]; + * u32 data_len; + * + * // read data_buf and 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 + * ----------------------------------------------------------------------------- + * + * vg_msg_cmd cmd; + * while( vg_msg_next( &data, &cmd ) ){ + * 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 ); + * } + */ 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 + /* 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_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, + + /* 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; -struct vg_msg{ - u32 cur,max; +typedef struct vg_msg_cursor vg_msg_cursor; +struct vg_msg +{ + u32 max; u8 *buf; - u32 depth; + + /* reading */ + struct vg_msg_cursor + { + u32 co, depth; + } + cur; - enum vg_msg_error{ + enum vg_msg_error + { k_vg_msg_error_OK, k_vg_msg_error_unbalanced, k_vg_msg_error_overflow, @@ -30,177 +147,53 @@ struct vg_msg{ error; }; -struct vg_msg_cmd{ +struct vg_msg_cmd +{ u8 code; 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; -}; - -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; -} - -static void vg_msg_exchbuf( vg_msg *msg, int write, 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]; - else buf[i] = msg->buf[ msg->cur ++ ]; - } -} - -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 ); - if( !str[i] ) break; - } -} - -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 ]); - - while( (c = msg->buf[ msg->cur ++ ]) ){ - if( msg->cur >= msg->max ){ - msg->error = k_vg_msg_error_overflow; - return 0; - } - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - } - - *djb2 = hash; - return str; -} - -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_wstr( msg, name ); -} - -static void vg_msg_end_frame( vg_msg *msg ){ - if( msg->error != k_vg_msg_error_OK ) return; - if( !msg->depth ){ - msg->error = k_vg_msg_error_unbalanced; - return; - } - msg->depth --; - vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_endframe }, 1 ); -} - -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_wstr( msg, key ); - vg_msg_wstr( msg, value ); -} - -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_wstr( msg, key ); - vg_msg_exchbuf( msg, 1, (u8 *)(&len), 4 ); - vg_msg_exchbuf( msg, 1, bin, len ); -} - -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 ); -} - -#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));\ - } - -static int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd ){ - vg_msg_exchbuf( msg, 0, &cmd->code, 1 ); - if( msg->error != k_vg_msg_error_OK ) return 0; - - if( cmd->code == k_vg_msg_code_frame ){ - cmd->key = vg_msg_rstr( msg, &cmd->key_djb2 ); - msg->depth ++; - } - else if( cmd->code == k_vg_msg_code_endframe ){ - if( !msg->depth ){ - msg->error = k_vg_msg_error_unbalanced; - return 0; - } - msg->depth --; - } - else if( cmd->code >= k_vg_msg_code_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 ); - } - 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_code_kvbin ){ - u32 len; - vg_msg_exchbuf( msg, 0, (u8 *)(&len), 4 ); - if( msg->error != k_vg_msg_error_OK ) return 0; - cmd->value._buf = &msg->buf[ msg->cur ]; - msg->cur += len; - if( msg->cur > msg->max ){ - msg->error = k_vg_msg_error_overflow; - } - } - else{ - msg->error = k_vg_msg_error_unhandled_cmd; - } - } - else{ - msg->error = k_vg_msg_error_unhandled_cmd; - } - - if( msg->error != k_vg_msg_error_OK ) return 0; - else return 1; -} - -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; - } - return 0; -} + u32 len; /* set if binary type */ +}; -#endif /* VG_MSG_H */ +void vg_msg_wbuf( vg_msg *msg, u8 *buf, u32 len ); +void vg_msg_rbuf( vg_msg *msg, u8 *buf, u32 len ); +void vg_msg_wstr( vg_msg *msg, const char *str ); +const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 ); +void vg_msg_frame( vg_msg *msg, const char *name ); +void vg_msg_end_frame( vg_msg *msg ); +void vg_msg_wkvstr( vg_msg *msg, const char *key, const char *value ); +void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len ); +void vg_msg_wkvnum( vg_msg *msg, const char *key, + u8 type, u8 count, void *data ); +u32 vg_msg_cmd_array_count( u8 code ); +u32 vg_msg_cmd_type_size( u8 code ); +u32 vg_msg_cmd_bytecount( u8 code ); +u8 vg_msg_count_bits( u32 count ); + +void vg_msg_init( vg_msg *msg, u8 *buffer, u32 len ); +int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd ); +int vg_msg_skip_frame( vg_msg *msg ); +int vg_msg_seekframe( vg_msg *msg, const char *name ); +u64 vg_msg_cast_to_u64( const void *src, u8 src_base, u8 src_size ); +i64 vg_msg_cast_to_i64( const void *src, u8 src_base, u8 src_size ); +f64 vg_msg_cast_to_f64( const void *src, u8 src_base, u8 src_size ); +void vg_msg_cast( const void *src, u8 src_code, void *dst, u8 dst_code ); + +int vg_msg_getkvcmd( vg_msg *msg, const char *key, vg_msg_cmd *cmd ); + +/* + * Read a integral KV out to dst, and perform conversion if needed + */ +int vg_msg_getkvintg( vg_msg *msg, const char *key, u8 type, void *dst, + void *default_value ); + +/* helper for reading string kvs. returns NULL if not found */ +const char *vg_msg_getkvstr( vg_msg *msg, const char *key ); +int vg_msg_getkvvecf( vg_msg *msg, const char *key, u8 type, + void *v, void *default_value ); +void vg_msg_print( vg_msg *msg, u32 len );