fixed some complaints from mingw/gcc
authorhgn <hgodden00@gmail.com>
Sat, 27 May 2023 04:18:36 +0000 (05:18 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 27 May 2023 04:18:36 +0000 (05:18 +0100)
vg_console.h
vg_msg.h
vg_platform.h

index c25dc6fa1ab5836f631c1be5544127be57bab2f9..d2f8d878edee8763179e2ab57d8d35b3ff4310ce 100644 (file)
@@ -459,7 +459,7 @@ VG_STATIC void console_update_suggestions(void)
    const char *args[8];
 
    int token_count = vg_console_tokenize( vg_console.input, temp, args );
-
+   if( !token_count ) return;
    vg_console.suggestion_pastepos = args[token_count-1]-temp;
 
    /* Score all our commands and cvars */
index cc38e859cc0a9b34eb217e9c88da2af3d24ded87..83bc0863f6f40942a44731c0c47e445a3079f6a2 100644 (file)
--- a/vg_msg.h
+++ b/vg_msg.h
@@ -1,6 +1,95 @@
 #ifndef VG_MSG_H
 #define VG_MSG_H
 #include "vg_stdint.h"
+#include "vg_platform.h"
+
+/*
+ * 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_wkvint( &data, "kvint", i32 value=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_wkvint( &data, "capacity", i32 value=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 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 )
+ *         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_code_signed )
+ *       print( "building capacity: %d\n", capacity.value._i32 );
+ *
+ *    vg_msg_skip_frame( &building );
+ * }
+ *
+ */
 
 enum vg_msg_code{
    k_vg_msg_code_end      = 0,
@@ -11,7 +100,8 @@ enum vg_msg_code{
    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_float    = 0x20,
+   k_vg_msg_code_integer  = k_vg_msg_code_signed|k_vg_msg_code_unsigned
 };
 
 typedef struct vg_msg vg_msg;
@@ -20,6 +110,9 @@ struct vg_msg{
    u32 cur,max;
    u8 *buf;
    u32 depth;
+
+   /* reading */
+   u32 rframe_depth, rframe_cur;
    
    enum vg_msg_error{
       k_vg_msg_error_OK,
@@ -45,14 +138,18 @@ struct vg_msg_cmd{
    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 or read a buffer from msg, rang checked. */
 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 ){
@@ -65,6 +162,7 @@ static void vg_msg_exchbuf( vg_msg *msg, int write, u8 *buf, u32 len ){
    }
 }
 
+/* write null terminated string to stream */
 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++ ){
@@ -73,6 +171,7 @@ static void vg_msg_wstr( vg_msg *msg, const char *str ){
    }
 }
 
+/* read null terminated string, range check and generate hash (djb2) */
 static const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 ){
    if( msg->error != k_vg_msg_error_OK ) return 0;
 
@@ -91,6 +190,7 @@ static const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 ){
    return str;
 }
 
+/* begin a new frame in message stream */
 static void vg_msg_frame( vg_msg *msg, const char *name ){
    if( msg->error != k_vg_msg_error_OK ) return;
 
@@ -99,6 +199,7 @@ static void vg_msg_frame( vg_msg *msg, const char *name ){
    vg_msg_wstr( msg, name );
 }
 
+/* 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 ){
@@ -109,12 +210,14 @@ static void vg_msg_end_frame( vg_msg *msg ){
    vg_msg_exchbuf( msg, 1, (u8[]){ k_vg_msg_code_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_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_wstr( msg, key );
@@ -122,6 +225,7 @@ static void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len ){
    vg_msg_exchbuf( msg, 1, 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;
@@ -130,6 +234,15 @@ static void vg__msg_wkvgen( vg_msg *msg, const char *key,
    vg_msg_exchbuf( msg, 1, value, size );
 }
 
+/* 
+ * 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
+ */
+
 #define vg_msg_wkvint( MSGPTR, KEY, DECL ){ \
    DECL; \
    vg__msg_wkvgen(MSGPTR, KEY, k_vg_msg_code_signed, &value, sizeof(value));\
@@ -143,6 +256,14 @@ static void vg__msg_wkvgen( vg_msg *msg, const char *key,
    vg__msg_wkvgen(MSGPTR, KEY, k_vg_msg_code_float, &value, sizeof(value));\
    }
 
+/*
+ * The stream reading interface
+ * -----------------------------------------------------------------------------
+ */
+
+/* move the cursor through the next message. it will always read in the value or
+ * 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 );
    if( msg->error != k_vg_msg_error_OK ) return 0;
@@ -193,6 +314,7 @@ static int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd ){
    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;
 
@@ -203,4 +325,83 @@ static int vg_msg_skip_frame( vg_msg *msg ){
    return 0;
 }
 
+/*
+ * A more friendly but slower interface 
+ * -----------------------------------------------------------------------------
+ */
+
+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 );
+   
+   vg_msg_cmd cmd;
+   while( vg_msg_next( msg, &cmd ) ){
+      if( msg->depth < msg->rframe_depth ){
+         vg_msg_framereset(msg);
+         return 0;
+      }
+      if( msg->depth != msg->rframe_depth+1 ) continue;
+      if( cmd.code == k_vg_msg_code_frame ){
+         if( VG_STRDJB2_EQ( name, cmd.key, cmd.key_djb2 ) ){
+            msg->rframe_cur = msg->cur;
+            msg->rframe_depth = msg->depth;
+            return 1;
+         }
+      }
+   }
+
+   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_code_end;
+   kv.key = "";
+   kv.key_djb2 = 0;
+   kv.value._u64 = 0;
+   kv.key_djb2 = 0;
+
+   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_code_kv )
+         if( VG_STRDJB2_EQ( key, cmd.key, cmd.key_djb2 ) ) 
+            return cmd;
+   }
+
+   return kv;
+}
+
+/* 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_code_kvstring ) return cmd.value._buf;
+   else return NULL;
+}
+
+
 #endif /* VG_MSG_H */
index 2ebc506ea032249a1985507afe4cbd19ba029b0c..1b0317c0c30b0b43ff971fa97c01370eb89987de 100644 (file)
@@ -96,6 +96,7 @@ VG_STATIC void vg_strnull( vg_str *str, char *buffer, u32 len )
 
 VG_STATIC void vg_strcat( vg_str *str, const char *append )
 {
+   if( !append ) return;
    for( u32 i=0; str->i < str->len; i++, str->i ++ ){
       str->buffer[ str->i ] = append[i];