KV
authorhgn <hgodden00@gmail.com>
Sun, 29 Jun 2025 13:01:25 +0000 (14:01 +0100)
committerhgn <hgodden00@gmail.com>
Sun, 29 Jun 2025 13:01:25 +0000 (14:01 +0100)
vg_build.h
vg_bvh.c
vg_io.c
vg_kv.c
vg_kv.h
vg_mem.c
vg_mem.h

index c34f3932e2645efe897bc977c0f3c94c24071c41..40266908c921f4721dd75a258c2779c2503d1217 100644 (file)
@@ -282,7 +282,6 @@ vg_compiler_run( struct vg_project *project,
    vg_strcat( &cmd, "  -Wall -ferror-limit=10\\\n"
       "    -Wno-unused-function -Wno-unused-variable\\\n"
       "    -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
-      "    -Wunused-result\\\n"
    );
 
    if( env->compiler != k_compiler_clang )
index 05edae7271895bc1262888271d3b7db9601557bb..9127be5bb1949aafc2aa24cb599a0f27cf5f16ed 100644 (file)
--- a/vg_bvh.c
+++ b/vg_bvh.c
@@ -104,7 +104,7 @@ bh_tree *bh_create( vg_stack_allocator *stack, bh_system *system, void *user, u3
 
    totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count;
 
-   if( stack ) vg_stack_resize_last( stack, totsize );
+   if( stack ) bh = vg_stack_resize_last( stack, totsize );
    else        bh = vg_realloc( bh, totsize );
 
    vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) );
diff --git a/vg_io.c b/vg_io.c
index a293958c13b56086832bbc1c6151599a286df27b..e75957271502e8bda487b293930234fd4f785773 100644 (file)
--- a/vg_io.c
+++ b/vg_io.c
@@ -208,7 +208,7 @@ void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool
       /* read in chunks */
       for( u32 i=0; 1; i++ )
       {
-         vg_stack_extend_last( stack, VG_FILE_IO_CHUNK_SIZE );
+         buffer = vg_stack_extend_last( stack, VG_FILE_IO_CHUNK_SIZE );
          u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f );
          current += l;
 
@@ -238,11 +238,11 @@ void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool
 
       if( text )
       {
-         vg_stack_extend_last( stack, 1 );
+         buffer = vg_stack_extend_last( stack, 1 );
          buffer[ current ++ ] = '\0';
       }
 
-      vg_stack_resize_last( stack, current );
+      buffer = vg_stack_resize_last( stack, current );
                fclose( f );
 
       *size = (u32)current;
diff --git a/vg_kv.c b/vg_kv.c
index 39f7831feba874941ffb24bc5b2922cfb51ad562..a4d838814d1261511a100718df4f25ebbe7abe22 100644 (file)
--- a/vg_kv.c
+++ b/vg_kv.c
@@ -1,3 +1,268 @@
 #include "vg_kv.h"
 
+void vg_kv_parse( vg_kvs *out_kvs, const char *source, vg_stack_allocator *stack )
+{
+   out_kvs->source_buffer = source;
+   out_kvs->kv_count = 1;
+   out_kvs->kvs = vg_stack_allocate( stack, sizeof(vg_kv), 8, "KV Metadata buffer" );
+   vg_zero_mem( out_kvs->kvs, sizeof(vg_kv) );
 
+   u32 token_start=0,
+       token_length=0,
+       token_hash=0,
+       depth=0;
+   char delim = 0;
+
+   struct
+   {
+      u32 frame_id, latest_child_id;
+   }
+   frame_stack[ 64 ];
+   frame_stack[0].frame_id = 0;
+   frame_stack[0].latest_child_id = 0;
+
+   u32 t0_start=0, t0_length=0, t0_hash=0;
+
+   for( u32 i=0; i<0xffffffff; i ++ )
+   {
+      out_kvs->source_length = i;
+
+      char c = source[i];
+      if( c == '\0' )
+         break;
+
+      u32 link_id = 0, link_depth = 0;
+
+      if( (delim && (c == delim)) || (!delim && (c==' '||c=='\t'||c=='\r'||c=='\n'||c=='{'||c=='}')) )
+      {
+         if( token_length )
+         {
+            token_length --;
+            if( t0_length )
+            {
+               /* pair */
+               link_id = out_kvs->kv_count ++;
+               link_depth = depth;
+
+               out_kvs->kvs = vg_stack_extend_last( stack, sizeof(vg_kv) );
+               vg_kv *kv = &out_kvs->kvs[ link_id ];
+               kv->key_info = (0xFFFFF & t0_hash) | (0x3FF & t0_length)<<20 | (0x1) << 30;
+               kv->key_offset = t0_start;
+               kv->brother_offset = 0; /* deffered */
+               kv->value.offset_from_key = token_start - t0_start;
+               kv->value.length = token_length;
+
+               t0_length = 0;
+            }
+            else
+            {
+               t0_start = token_start;
+               t0_length = token_length;
+               t0_hash = token_hash;
+            }
+
+            token_length = 0;
+         }
+
+         if( c=='{'||c=='}'||c=='\n' )
+         {
+            /* SYNTAX TOKEN */
+            if( c == '{' )
+            {
+               link_id = out_kvs->kv_count ++;
+               link_depth = depth;
+
+               out_kvs->kvs = vg_stack_extend_last( stack, sizeof(vg_kv) );
+               vg_kv *kv = &out_kvs->kvs[ link_id ];
+               kv->brother_offset = 0; /* deffered */
+               kv->children = 0;
+               if( t0_length )
+               {
+                  /* frame with name */
+                  kv->key_info = (0xFFFFF & t0_hash) | (0x3FF & t0_length) << 20;
+                  kv->key_offset = t0_start;
+               }
+               else
+               {
+                  /* frame with no name */
+                  kv->key_info = 5381;
+                  kv->key_offset = 0;
+               }
+
+               t0_length = 0;
+               depth ++;
+               frame_stack[ depth ].latest_child_id = 0;
+               frame_stack[ depth ].frame_id = link_id;
+            }
+            else if( c == '}' )
+            {
+               if( depth )
+                  depth --;
+               t0_length = 0;
+            }
+         }
+
+         delim = 0;
+      }
+      else
+      {
+         if( token_length )
+         {
+            token_length ++;
+            token_hash = ((token_hash << 5) + token_hash) + (u32)c;
+         }
+         else
+         {
+            if( c=='"'||c=='\'' )
+            {
+               delim = c;
+               token_start = i+1;
+               token_length = 1;
+               token_hash = 5381;
+            }
+            else
+            {
+               token_start = i;
+               token_length = 2;
+               token_hash = ((5381<<5)+5381) + (u32)c;
+            }
+         }
+      }
+
+      if( link_id )
+      {
+         u32 parent_id = frame_stack[link_depth].frame_id;
+         vg_kv *parent = &out_kvs->kvs[ parent_id ];
+         parent->children ++;
+
+         u32 brother_id = frame_stack[link_depth].latest_child_id;
+         if( brother_id )
+         {
+            vg_kv *brother = &out_kvs->kvs[ brother_id ];
+            VG_ASSERT( brother->brother_offset == 0 );
+            brother->brother_offset = link_id - brother_id;
+         }
+         frame_stack[ link_depth ].latest_child_id = link_id;
+      }
+   }
+}
+
+u32 vg_kv_type( vg_kvs *kvs, u32 kv_id ){ return (kvs->kvs[ kv_id ].key_info >> 30) & 0x3; }
+
+const char *vg_kv_key( vg_kvs *kvs, u32 kv_id, u32 *out_length )
+{
+   vg_kv *kv = &kvs->kvs[ kv_id ];
+   *out_length = (kv->key_info >> 20) & 0x3FF;
+   return kvs->source_buffer + kv->key_offset;
+}
+
+const char *vg_kv_value( vg_kvs *kvs, u32 kv_id, u32 *out_length )
+{ 
+   u32 type = vg_kv_type( kvs, kv_id );
+   if( type == 0x0 )
+      return NULL;
+   else
+   {
+      vg_kv *kv = &kvs->kvs[ kv_id ];
+      *out_length = kv->value.length;
+      return kvs->source_buffer + (kv->key_offset + kv->value.offset_from_key);
+   }
+}
+
+u32 vg_kv_child_count( vg_kvs *kvs, u32 kv_id )
+{
+   u32 type = vg_kv_type( kvs, kv_id );
+   if( type == 0x0 )
+      return kvs->kvs[ kv_id ].children;
+   else
+      return 0;
+}
+
+u32 vg_kv_child( vg_kvs *kvs, u32 root_id, u32 index )
+{
+   VG_ASSERT( index == 0 );
+
+   if( vg_kv_child_count( kvs, root_id ) )
+      return root_id +1;
+   else
+      return 0;
+}
+
+u32 vg_kv_next( vg_kvs *kvs, u32 kv_id )
+{
+   u32 offset = kvs->kvs[ kv_id ].brother_offset;
+   if( offset )
+      return kv_id + offset;
+   else 
+      return 0;
+}
+
+u32 vg_kv_find( vg_kvs *kvs, u32 root_id, const char *key )
+{
+   u32 hash = vg_strdjb2( key );
+   u32 child_id = vg_kv_child( kvs, root_id, 0 );
+   while( child_id )
+   {
+      vg_kv *kv = &kvs->kvs[ child_id ];
+      if( ((kv->key_info ^ hash) & 0xFFFFF) == 0 )
+      {
+         u32 key_length;
+         const char *child_key = vg_kv_key( kvs, child_id, &key_length );
+         if( child_key )
+         {
+            for( u32 i=0; i<key_length; i ++ )
+               if( child_key[i] != key[i] )
+                  goto next;
+
+            return child_id;
+         }
+      }
+
+ next:child_id = vg_kv_next( kvs, child_id );
+   }
+
+   return 0;
+}
+
+void vg_kv_print_info( vg_kvs *kvs )
+{
+   vg_low( "Compression ratio: %.2f%%\n", ((f32)(kvs->kv_count * sizeof(vg_kv)) / (f32)kvs->source_length )*100.0f );
+}
+
+void vg_kv_print_tree( vg_kvs *kvs, u32 root_id, u32 depth )
+{
+   VG_ASSERT( vg_kv_type( kvs, root_id ) == 0x0 );
+
+   const char *k_whitespace = "                                                                                            ";
+
+   u32 root_len;
+   const char *root_str = vg_kv_key( kvs, root_id, &root_len );
+   vg_info( "%.*s\"%.*s\"\n", depth*2, k_whitespace, root_len, root_str );
+   vg_info( "%.*s{\n", depth*2, k_whitespace );
+   depth ++;
+
+   u32 child_id = vg_kv_child( kvs, root_id, 0 );
+   while( child_id )
+   {
+      if( vg_kv_type( kvs, child_id ) == 0x0 )
+         vg_kv_print_tree( kvs, child_id, depth );
+      else
+      {
+         u32 key_len;
+         const char *key_str = vg_kv_key( kvs, child_id, &key_len );
+
+         u32 value_len;
+         const char *value_str = vg_kv_value( kvs, child_id, &value_len );
+
+         if( key_str && value_str )
+            vg_info( "%.*s\"%.*s\" \"%.*s\"\n", depth*2, k_whitespace, key_len, key_str, value_len, value_str );
+         else
+            vg_error( "%.*s<KV ERROR>\n", depth*2, k_whitespace );
+      }
+
+      child_id = vg_kv_next( kvs, child_id );
+   }
+
+   depth --;
+   vg_info( "%.*s}\n", depth*2, k_whitespace );
+}
diff --git a/vg_kv.h b/vg_kv.h
index ee11558c8823f2ec431048ddad5a8a02803e62eb..0e0214d1bd829c33a39a83fdafb4df2b19c79aef 100644 (file)
--- a/vg_kv.h
+++ b/vg_kv.h
@@ -1,11 +1,22 @@
 #pragma once
 #include "vg_platform.h"
 
+typedef struct vg_kvs vg_kvs;
+typedef struct vg_kv vg_kv;
+struct vg_kvs
+{
+   const char *source_buffer;
+   u32 source_length;
+
+   vg_kv *kvs;
+   u32 kv_count;
+};
+
 struct vg_kv
 {
    u32 key_info;      /* 20 bit hash, 10 bit key length, 2 bit type */
-   u32 key_offset;    /* into the raw text buffer */
-   u32 brother_offset;/* 24 bits, relative jump past all descendents to the next key */
+   u32 key_offset;    /* 32 bit, indexes into the raw text buffer  */
+   u32 brother_offset;/* 24 bits, relative jump past all descendents to the next key. If 0, no brothers */
 
    union
    {
index 2e69ad6a9971b87073caff7fa4c96cb7cb3db904..fe93cca69091658211edb647caa50106a21130ec 100644 (file)
--- a/vg_mem.c
+++ b/vg_mem.c
@@ -170,7 +170,7 @@ void vg_stack_set_flags_last( vg_stack_allocator *stack, u16 append_flags )
    meta->flags |= append_flags;
 }
 
-void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size )
+void *vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size )
 {
    u32 base_offset = stack->used - stack->last_allocation_totalsize,
        block_size  = new_size;
@@ -186,14 +186,15 @@ void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size )
    vg_stack_growmaybe( stack, new_usage );
    stack->used = new_usage;
    stack->last_allocation_totalsize = block_size;
+   return stack->data + (new_usage - new_size);
 }
 
-void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes )
+void *vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes )
 {
    u32 current_size = stack->last_allocation_totalsize;
    if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
       current_size -= sizeof(vg_allocation_meta);
-   vg_stack_resize_last( stack, current_size + extra_bytes );
+   return vg_stack_resize_last( stack, current_size + extra_bytes );
 }
 
 void *vg_stack_pop_last( vg_stack_allocator *stack )
index 9c91111329c643468aad392007a3aaba9a5758ed..34dbe5961927c941a48fcbb8fab75174be45fc68 100644 (file)
--- a/vg_mem.h
+++ b/vg_mem.h
@@ -67,8 +67,11 @@ vg_stack_allocator *vg_stack_make_substack( vg_stack_allocator *parent, u32 capa
 
 #define VG_STACK_ALLOCATE_STRUCT( STACK, STRUCT ) vg_stack_allocate( STACK, sizeof(STRUCT), alignof(STRUCT), NULL )
 
-void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size );
-void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes );
+__attribute__((warn_unused_result))
+void *vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size );
+
+__attribute__((warn_unused_result))
+void *vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes );
 
 /*
  * The following are availible if allocator has the flag METADATA set