* 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" );
* 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" );
*
* // 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
* -----------------------------------------------------------------------------
* 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{
/* 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,
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; i<len; i++ ){
- msg->buf[ 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; i<len; i++ ){
- buf[i] = msg->buf[ msg->cur ++ ];
+ buf[i] = msg->buf[ msg->cur.co ++ ];
}
}
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;
}
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 );
}
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 */
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;
}
/*
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;
}
* -----------------------------------------------------------------------------
*/
-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; i<VG_MIN(src_n,dst_n); i ++ ){
+ const void *ptr_s = src + i*src_s;
+ void *ptr_d = dst + i*dst_s;
+
+ if( dst_b == k_vg_msg_unsigned ){
+ u64 a = vg_msg_cast_to_u64( ptr_s, src_b, src_s );
+ if ( dst_s == 1 ) *((u8 *)ptr_d) = (u8 )a;
+ else if( dst_s == 2 ) *((u16*)ptr_d) = (u16)a;
+ else if( dst_s == 4 ) *((u32*)ptr_d) = (u32)a;
+ else if( dst_s == 8 ) *((u64*)ptr_d) = a;
+ }
+ else if( dst_b == k_vg_msg_signed ){
+ i64 a = vg_msg_cast_to_i64( ptr_s, src_b, src_s );
+ if ( dst_s == 1 ) *((i8 *)ptr_d) = (i8 )a;
+ else if( dst_s == 2 ) *((i16*)ptr_d) = (i16)a;
+ else if( dst_s == 4 ) *((i32*)ptr_d) = (i32)a;
+ else if( dst_s == 8 ) *((i64*)ptr_d) = a;
+ }
+ else {
+ f64 a = vg_msg_cast_to_f64( ptr_s, src_b, src_s );
+ if ( dst_s == 4 ) *((f32*)ptr_d) = (f32)a;
+ else if( dst_s == 8 ) *((f64*)ptr_d) = a;
+ }
+ }
+ }
+}
- if( (sized_type == k_vg_msg_unsigned) || (sized_type == k_vg_msg_signed) ){
- u32 bytes = vg_msg_sized_bytecount( cmd->code );
- if( bytes > 8 ) bytes = 8;
- for( u32 i=0; i<bytes; i ++ ) dst[i] = src[i];
+/*
+ * search in current level from cursor, to find kv cmd
+ * returns 0 if not found
+ * Cursor does not move
+ * If found, the kv command is written to cmd
+ */
+static int vg_msg_getkvcmd( vg_msg *msg, const char *key, vg_msg_cmd *cmd ){
+ vg_msg_cursor orig = msg->cur;
+ 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; i<bytes; i ++ ) dst[i] = src[i];
+#define _GET_KV_INTG_HELPER( TYPE ) \
+static TYPE vg_msg_getkv##TYPE( vg_msg *msg, const char *key, \
+ TYPE default_value ){ \
+ vg_msg_cmd cmd; \
+ if( vg_msg_getkvcmd( msg, key, &cmd ) ){ \
+ TYPE v; \
+ vg_msg_cast( cmd.value, cmd.code, &v, k_vg_msg_##TYPE ); \
+ return v; \
+ } \
+ else \
+ return default_value; \
}
-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 );
- return vg_msg_read_as_u64( &cmd );
+#define _GET_KV_VEC_HELPER( TYPE ) \
+static int vg_msg_getkv##TYPE( vg_msg *msg, const char *key, \
+ TYPE v, \
+ TYPE default_value ){ \
+ vg_msg_cmd cmd; \
+ if( vg_msg_getkvcmd( msg, key, &cmd ) ){ \
+ vg_msg_cast( cmd.value, cmd.code, v, k_vg_msg_##TYPE ); \
+ return 1; \
+ } \
+ else \
+ if ( default_value ) \
+ vg_msg_cast( default_value, k_vg_msg_##TYPE, v, k_vg_msg_##TYPE ); \
+ return 0; \
}
+_GET_KV_INTG_HELPER( u8 )
+_GET_KV_INTG_HELPER( u16 )
+_GET_KV_INTG_HELPER( u32 )
+_GET_KV_INTG_HELPER( u64 )
+_GET_KV_INTG_HELPER( i8 )
+_GET_KV_INTG_HELPER( i16 )
+_GET_KV_INTG_HELPER( i32 )
+_GET_KV_INTG_HELPER( i64 )
+_GET_KV_INTG_HELPER( f32 )
+_GET_KV_INTG_HELPER( f64 )
+_GET_KV_VEC_HELPER( v2f )
+_GET_KV_VEC_HELPER( v3f )
+_GET_KV_VEC_HELPER( v4f )
+
/* debug the thing */
-static void vg_msg_print( vg_msg *msg ){
- vg_msg b = *msg;
- b.cur = 0;
+static void vg_msg_print( vg_msg *msg, u32 len ){
+ if( msg->error != 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<b.depth-1; i++ ) printf( " " );
- printf( "'%s'[%u]{\n", cmd.key, cmd.key_djb2 );
+ for( u32 i=0; i<b.cur.depth-1; i++ ) printf( " " );
+ printf( "'%s'{\n", cmd.key );
}
else {
- for( u32 i=0; i<b.depth; i++ ) printf( " " );
+ for( u32 i=0; i<b.cur.depth; i++ ) printf( " " );
if( cmd.code == k_vg_msg_endframe )
printf( "}\n" );
- else if( cmd.code == k_vg_msg_kvstring ){
- printf( "'%s'[%u]: '%s'[%u]\n", cmd.key, cmd.key_djb2,
- (char *)cmd.value, cmd.value_djb2 );
+ else if( cmd.code == k_vg_msg_kvstring )
+ printf( "'%s': '%s'\n", cmd.key, (char *)cmd.value );
+ else if( cmd.code == k_vg_msg_kvbin )
+ printf( "'%s': <binary data> (%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<count; i++ ){
+ const void *p = cmd.value + size*i;
+
+ if( base == k_vg_msg_unsigned )
+ printf( "%lu", vg_msg_cast_to_u64( p, base, size ) );
+ else if( base == k_vg_msg_signed )
+ printf( "%ld", vg_msg_cast_to_i64( p, base, size ) );
+ else
+ printf( "%f", vg_msg_cast_to_f64( p, base, size ));
+
+ if( i+1<count ) printf(", ");
+ }
+
+ if( count > 1 ) printf( "'}'" );
+ printf( "\n" );
}
- else
- printf( "'%s'[%u]: <binary data>\n", cmd.key, cmd.key_djb2 );
}
}
}