}
/* group control */
-VG_API void _vg_async_context_push_groups( u16 groups )
+VG_API void _vg_async_context_push_groups( u16 groups, bool exclusive )
{
struct vg_thread_context *context = SDL_TLSGet( vg.thread_tls );
context->async_group_depth ++;
VG_ASSERT( context->async_group_depth < VG_TEMP_STACK_MAX );
- context->async_groups[ context->async_group_depth ] = groups | context->async_groups[ context->async_group_depth-1 ];
+
+ if( !exclusive )
+ groups |= context->async_groups[ context->async_group_depth-1 ];
+
+ context->async_groups[ context->async_group_depth ] = groups;
}
VG_API void _vg_async_context_pop_groups(void)
VG_API void _vg_add_exit_function( void( *fn )( void ) )
{
+ _vg_async_context_push_groups( 0, 1 );
vg_async_task *task = vg_create_task( &vg.exit_tasks, sizeof(struct exit_task), VG_ASYNC_CRIT, "engine exit (No info)" );
struct exit_task *out_args = vg_task_buffer( &vg.exit_tasks, task );
out_args->fn = fn;
vg_task_send( &vg.exit_tasks, task, (vg_async_fn)vg_call_exit );
+ _vg_async_context_pop_groups();
}
#ifdef _WIN32
if( vg.fps_limit > 300 )
vg.fps_limit = 300;
- f64 min_frametime = 1.0/(f64)vg.fps_limit;
+ f64 min_frametime = 1.0/(f64)vg.fps_limit,
+ max_frametime = 1.0/(f64)24.0;
+
if( vg.time_frame_delta < min_frametime )
{
/* TODO: we can use high res nanosleep on Linux here */
goto L_filter_frame;
}
+ if( vg.time_frame_delta > max_frametime )
+ vg.time_frame_delta = max_frametime;
+
/* New fame starts here
* --------------------------------------------------------------------------------------------------------------- */
vg.time += vg.time_delta;
/* SDL event loop */
+ v2_zero( vg.mouse_wheel );
+ v2_zero( vg.mouse_delta );
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
ui_proc_utf8( &vg_ui.ctx, event.text.text );
}
vg.mouse_state = SDL_GetMouseState( &vg.mouse_pos[0], &vg.mouse_pos[1] );
- v2_zero( vg.mouse_wheel );
- v2_zero( vg.mouse_delta );
_vg_window_swap();
vg_audio_preupdate();
vg_process_inputs();
vg_steam_frame();
- if( 1 )
+ /* Update loop
+ * ----------------------------------------------------------------------------------------------------------- */
{
- /* Update loop
- * ----------------------------------------------------------------------------------------------------------- */
- {
- _vg_profiler_enter_block( vg.profiler, "update" );
- vg.gameloop_stage = k_gameloop_update;
- callback_fn( (vg_event_info[]){{ .type = k_vg_event_pre_update }} );
+ _vg_profiler_enter_block( vg.profiler, "update" );
+ vg.gameloop_stage = k_gameloop_update;
+ callback_fn( (vg_event_info[]){{ .type = k_vg_event_pre_update }} );
- /* Fixed update loop */
- vg.gameloop_stage = k_gameloop_update_fixed;
- vg.fixed_iterations = 0;
- vg_lines.enabled = vg_lines.render;
- vg.time_fixed_accumulator += vg.time_delta;
-
- while( vg.time_fixed_accumulator >= vg.time_fixed_delta )
- {
- callback_fn( (vg_event_info[]){{ .type = k_vg_event_fixed_update }} );
- vg_lines.enabled = 0;
- vg.time_fixed_accumulator -= vg.time_fixed_delta;
+ /* Fixed update loop */
+ vg.gameloop_stage = k_gameloop_update_fixed;
+ vg.fixed_iterations = 0;
+ vg_lines.enabled = vg_lines.render;
+ vg.time_fixed_accumulator += vg.time_delta;
- vg.fixed_iterations ++;
- if( vg.fixed_iterations == 8 )
- break;
- }
- vg_lines.enabled = vg_lines.render;
- vg.time_fixed_extrapolate = vg.time_fixed_accumulator / vg.time_fixed_delta;
+ while( vg.time_fixed_accumulator >= vg.time_fixed_delta )
+ {
+ callback_fn( (vg_event_info[]){{ .type = k_vg_event_fixed_update }} );
+ vg_lines.enabled = 0;
+ vg.time_fixed_accumulator -= vg.time_fixed_delta;
- vg.gameloop_stage = k_gameloop_update;
- callback_fn( (vg_event_info[]){{ .type = k_vg_event_post_update }} );
- _vg_profiler_exit_block( vg.profiler );
+ vg.fixed_iterations ++;
+ if( vg.fixed_iterations == 8 )
+ break;
}
+ vg_lines.enabled = vg_lines.render;
+ vg.time_fixed_extrapolate = vg.time_fixed_accumulator / vg.time_fixed_delta;
+
+ vg.gameloop_stage = k_gameloop_update;
+ callback_fn( (vg_event_info[]){{ .type = k_vg_event_post_update }} );
+ _vg_profiler_exit_block( vg.profiler );
+ }
+ if( vg_loader.loading_count == 0 )
+ {
/* Render loop
* ------------------------------------------------------------------------------------------------------------ */
+ _vg_profiler_enter_block( vg.profiler, "render" );
+ vg.gameloop_stage = k_gameloop_rendering;
+ callback_fn( (vg_event_info[]){{ .type = k_vg_event_render }} );
+ _vg_profiler_exit_block( vg.profiler );
+
+ /* ui --------------------------------------------------- */
+ vg.gameloop_stage = k_gameloop_ui;
+
+ ui_prerender( &vg_ui.ctx );
+ vg_ui_set_screen( _vg_window.w, _vg_window.h );
+ ui_update_mouse( &vg_ui.ctx, (ui_px[2]){ vg.mouse_pos[0], vg.mouse_pos[1] }, vg.mouse_state );
+
+ if( vg_console.enabled )
+ ui_ignore_input_frames( &vg_ui.ctx, 10 );
+ callback_fn( (vg_event_info[]){{ .type = k_vg_event_gui, .gui = { .ctx = &vg_ui.ctx } }} );
+ if( vg_console.enabled )
{
- /* render -------------------------------------------------- */
- _vg_profiler_enter_block( vg.profiler, "render" );
- vg.gameloop_stage = k_gameloop_rendering;
- callback_fn( (vg_event_info[]){{ .type = k_vg_event_render }} );
- _vg_profiler_exit_block( vg.profiler );
-
- /* ui --------------------------------------------------- */
- vg.gameloop_stage = k_gameloop_ui;
-
- ui_prerender( &vg_ui.ctx );
- vg_ui_set_screen( _vg_window.w, _vg_window.h );
- ui_update_mouse( &vg_ui.ctx, (ui_px[2]){ vg.mouse_pos[0], vg.mouse_pos[1] }, vg.mouse_state );
-
- if( vg_console.enabled )
- ui_ignore_input_frames( &vg_ui.ctx, 10 );
- callback_fn( (vg_event_info[]){{ .type = k_vg_event_gui, .gui = { .ctx = &vg_ui.ctx } }} );
- if( vg_console.enabled )
- {
- ui_ignore_input_frames( &vg_ui.ctx, 0 );
- ui_capture_mouse( &vg_ui.ctx, 1 );
- vg_console_draw( &vg_ui.ctx );
- }
-
- _vg_settings_gui( &vg_ui.ctx );
- vg_framebuffer_ui( &vg_ui.ctx );
- _vg_magi_render( &vg_ui.ctx );
- ui_postrender( &vg_ui.ctx, vg.time_frame_delta );
- vg_ui_post_update();
+ ui_ignore_input_frames( &vg_ui.ctx, 0 );
+ ui_capture_mouse( &vg_ui.ctx, 1 );
+ vg_console_draw( &vg_ui.ctx );
}
+
+ _vg_settings_gui( &vg_ui.ctx );
+ vg_framebuffer_ui( &vg_ui.ctx );
+ _vg_magi_render( &vg_ui.ctx );
+ ui_postrender( &vg_ui.ctx, vg.time_frame_delta );
+ vg_ui_post_update();
}
else
- {
vg_loader_render();
- }
if( vg.loader_ring > 0.01f )
{
if( (kvs->kv_page_count == VG_KV_PAGE_COUNT) || (kvs->kv_page_offset == 0) )
{
u32 page_size = sizeof(vg_kv)*VG_KV_PAGE_COUNT;
-
- // FIXME FIXME: 64 is causing issues with metadata enabled buffers!!!!!!!!!!!!!!!!!!!!!!
- // kv_page = vg_stack_allocate( kvs->stack, page_size, 64, "KV Page" );
- kv_page = vg_stack_allocate( kvs->stack, page_size, 8, "KV Page" );
+ kv_page = vg_stack_allocate( kvs->stack, page_size, 64, "KV Page" );
vg_zero_mem( kv_page, page_size );
kvs->kv_page_offset = vg_stack_offset( kvs->stack, kv_page );
kvs->kv_page_count = 0;
return kv_offset;
}
+/*
+ * Navigating, and read/writing the KV tree
+ * --------------------------------------------------------------------------------------------------------------------
+ */
+u32 vg_kv_type( vg_kvs *kvs, u32 kv_offset )
+{
+ vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+ return (kv->key_info >> 30) & 0x3;
+}
+
+const c8 *vg_kv_key( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
+{
+ if( kv_offset == 0 )
+ return NULL;
+
+ vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+ u32 length = (kv->key_info >> 20) & 0x3FF;
+ if( out_length )
+ *out_length = length;
+ return length? vg_stack_pointer( kvs->stack, kv->key_offset ): NULL;
+}
+
+const c8 *vg_kv_value( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
+{
+ if( kv_offset == 0 )
+ return NULL;
+ if( vg_kv_type( kvs, kv_offset ) == k_vg_kv_type_frame )
+ return NULL;
+ else
+ {
+ vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+ if( out_length )
+ *out_length = kv->value.length;
+ return vg_stack_pointer( kvs->stack, kv->key_offset + kv->value.offset_from_key );
+ }
+}
+
+u32 vg_kv_next( vg_kvs *kvs, u32 kv_offset )
+{
+ vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
+ return kv->brother_offset;
+}
+
+u32 vg_kv_child( vg_kvs *kvs, u32 root_offset, u32 index )
+{
+ if( vg_kv_type( kvs, root_offset ) == k_vg_kv_type_frame )
+ {
+ vg_kv *parent = vg_stack_pointer( kvs->stack, root_offset );
+ u32 offset = parent->first_child_offset;
+
+ for( u32 i=0; (i<index) && offset; i ++ )
+ {
+ vg_kv *kv = vg_stack_pointer( kvs->stack, offset );
+ offset = kv->brother_offset;
+ }
+ return offset;
+ }
+ else return 0;
+}
+
+u32 vg_kv_find( vg_kvs *kvs, u32 root_offset, const c8 *key )
+{
+ if( root_offset == 0 )
+ root_offset = kvs->root_offset;
+
+ u32 hash = vg_strdjb2( key );
+ u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
+ while( child_offset )
+ {
+ vg_kv *kv = vg_stack_pointer( kvs->stack, child_offset );
+ u32 key_length;
+ const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
+ if( ((kv->key_info ^ hash) & 0xFFFFF) == 0 )
+ {
+ u32 key_length;
+ const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
+ if( child_key )
+ {
+ for( u32 i=0; i<key_length; i ++ )
+ if( child_key[i] != key[i] )
+ goto next;
+
+ return child_offset;
+ }
+ }
+
+ next:child_offset = vg_kv_next( kvs, child_offset );
+ }
+ return 0;
+}
+
+bool vg_kv_read_vu32( vg_kvs *kvs, u32 root_offset, const c8 *key, u32 *default_value, u32 *out_value, u32 len )
+{
+ bool good = 1;
+ vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
+ for( u32 i=0; i<len; i ++ )
+ {
+ u64 value = 0;
+ if( vg_strp_u64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (u32)value;
+ else
+ {
+ good = 0;
+ if( default_value ) out_value[ i ] = default_value[ i ];
+ else out_value[ i ] = 0;
+ }
+ }
+ return good;
+}
+
+bool vg_kv_read_vf32( vg_kvs *kvs, u32 root_offset, const c8 *key, f32 *default_value, f32 *out_value, u32 len )
+{
+ bool good = 1;
+ vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
+ for( u32 i=0; i<len; i ++ )
+ {
+ f64 value = 0.0;
+ if( vg_strp_f64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (f32)value;
+ else
+ {
+ good = 0;
+ if( default_value ) out_value[ i ] = default_value[ i ];
+ else out_value[ i ] = 0.0f;
+ }
+ }
+ return good;
+}
+
+const c8 *vg_kv_read_string( vg_kvs *kvs, u32 root_offset, const c8 *key, const c8 *default_value )
+{
+ const c8 *value = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL );
+ return value? value: default_value;
+}
+
+u32 vg_kv_append_vu32( vg_kvs *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len )
+{
+ c8 formatted[ 1024 ];
+ vg_str value_str;
+ vg_strnull( &value_str, formatted, sizeof(formatted) );
+
+ for( u32 i=0; i<len; i++ )
+ {
+ vg_strcatu64( &value_str, values[i], 10 );
+ if( i+1!=len )
+ vg_strcatch( &value_str, ' ' );
+ }
+
+ if( !vg_strgood( &value_str ) )
+ return 0;
+
+ return vg_kv_append( kvs, parent_offset, key, formatted );
+}
+
+u32 vg_kv_append_vf32( vg_kvs *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len )
+{
+ c8 formatted[ 1024 ];
+ vg_str value_str;
+ vg_strnull( &value_str, formatted, sizeof(formatted) );
+
+ for( u32 i=0; i<len; i++ )
+ {
+ vg_strcatf64( &value_str, values[i], 10, 5 );
+ if( i+1!=len )
+ vg_strcatch( &value_str, ' ' );
+ }
+
+ if( !vg_strgood( &value_str ) )
+ return 0;
+
+ return vg_kv_append( kvs, parent_offset, key, formatted );
+}
+
+/*
+ * Parsing from formatted stream
+ * --------------------------------------------------------------------------------------------------------------------
+ */
void vg_kv_parser_init( vg_kv_parser *parser, vg_kvs *out_kvs, u32 root_offset )
{
VG_ASSERT( out_kvs->stack );
parser->frame_stack[0].frame_offset = root_offset;
}
-void vg_kv_link( vg_kv_parser *parser, u32 offset, u32 depth )
+static void vg_kv_parser_link( vg_kv_parser *parser, u32 offset, u32 depth )
{
u32 parent_offset = parser->frame_stack[ depth ].frame_offset;
vg_kv *parent = vg_stack_pointer( parser->kvs->stack, parent_offset );
kv->value.length = parser->token0_length;
parser->token1_length = 0;
- vg_kv_link( parser, vg_stack_offset( parser->kvs->stack, kv ), parser->depth );
+ vg_kv_parser_link( parser, vg_stack_offset( parser->kvs->stack, kv ), parser->depth );
}
else
{
parser->depth ++;
parser->frame_stack[ parser->depth ].latest_child_offset = 0;
parser->frame_stack[ parser->depth ].frame_offset = id;
- vg_kv_link( parser, id, depth );
+ vg_kv_parser_link( parser, id, depth );
parser->token1_length = 0;
}
else if( c == '}' )
}
}
-u32 vg_kv_type( vg_kvs *kvs, u32 kv_offset )
-{
- vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
- return (kv->key_info >> 30) & 0x3;
-}
-
-const c8 *vg_kv_key( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
-{
- if( kv_offset == 0 )
- return NULL;
-
- vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
- u32 length = (kv->key_info >> 20) & 0x3FF;
- if( out_length )
- *out_length = length;
- return length? vg_stack_pointer( kvs->stack, kv->key_offset ): NULL;
-}
-
-const c8 *vg_kv_value( vg_kvs *kvs, u32 kv_offset, u32 *out_length )
-{
- if( kv_offset == 0 )
- return NULL;
-
- if( vg_kv_type( kvs, kv_offset ) == 0x0 )
- return NULL;
- else
- {
- vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
- if( out_length )
- *out_length = kv->value.length;
- return vg_stack_pointer( kvs->stack, kv->key_offset + kv->value.offset_from_key );
- }
-}
-
-u32 vg_kv_next( vg_kvs *kvs, u32 kv_offset )
+void vg_kv_parser_print_info( vg_kv_parser *parser )
{
- vg_kv *kv = vg_stack_pointer( kvs->stack, kv_offset );
- return kv->brother_offset;
+ vg_low( "KV stats\n"
+ " bytes pages: %u\n"
+ " bytes strings: %u\n"
+ " source characters: %u. compression ratio: %.2f%%\n", parser->kvs->stat_memory_pages,
+ parser->stat_memory_strings,
+ parser->stat_source_characters,
+ (f32)(parser->stat_memory_strings+parser->kvs->stat_memory_pages) /
+ (f32)parser->stat_source_characters * 100.0f );
}
-u32 vg_kv_child( vg_kvs *kvs, u32 root_offset, u32 index )
+/*
+ * Writing KVS to a stream (formatted)
+ * --------------------------------------------------------------------------------------------------------------------
+ */
+void vg_kv_write_init( vg_kv_write *w, vg_stream *stream )
{
- if( vg_kv_type( kvs, root_offset ) == 0x0 )
- {
- vg_kv *parent = vg_stack_pointer( kvs->stack, root_offset );
- u32 offset = parent->first_child_offset;
-
- for( u32 i=0; (i<index) && offset; i ++ )
- {
- vg_kv *kv = vg_stack_pointer( kvs->stack, offset );
- offset = kv->brother_offset;
- }
- return offset;
- }
- else return 0;
-}
-
-u32 vg_kv_find( vg_kvs *kvs, u32 root_offset, const c8 *key )
-{
- if( root_offset == 0 )
- root_offset = kvs->root_offset;
-
- u32 hash = vg_strdjb2( key );
- u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
- while( child_offset )
- {
- vg_kv *kv = vg_stack_pointer( kvs->stack, child_offset );
- u32 key_length;
- const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
- if( ((kv->key_info ^ hash) & 0xFFFFF) == 0 )
- {
- u32 key_length;
- const c8 *child_key = vg_kv_key( kvs, child_offset, &key_length );
- if( child_key )
- {
- for( u32 i=0; i<key_length; i ++ )
- if( child_key[i] != key[i] )
- goto next;
-
- return child_offset;
- }
- }
-
- next:child_offset = vg_kv_next( kvs, child_offset );
- }
- return 0;
+ vg_zero_mem( w, sizeof(vg_kv_write) );
+ w->stream = stream;
}
static void vg_kv_write_indent( vg_kv_write *w )
{
for( u32 i=0; i<w->depth; i ++ )
- fputc( ' ', w->fp );
+ vg_stream_write( w->stream, (c8[]){ ' ' }, 1 );
}
static void vg_kv_write_string( vg_kv_write *w, const c8 *string, u32 length )
}
}
- if( delim ) fputc( delim, w->fp );
- for( u32 j=0; j<i; j ++ ) fputc( string[j], w->fp );
- if( delim ) fputc( delim, w->fp );
+ if( delim ) vg_stream_write( w->stream, (c8[]){ delim }, 1 );
+ vg_stream_write( w->stream, string, i );
+ if( delim ) vg_stream_write( w->stream, (c8[]){ delim }, 1 );
}
void vg_kv_write_block( vg_kv_write *w, const c8 *name, u32 name_length )
if( name )
{
vg_kv_write_string( w, name, name_length );
- fputc( '\n', w->fp );
+ vg_stream_write( w->stream, (c8[]){ '\n' }, 1 );
vg_kv_write_indent( w );
}
- fputc( '{', w->fp );
- fputc( '\n', w->fp );
+ vg_stream_write( w->stream, (c8[]){ '{', '\n' }, 2 );
w->depth ++;
}
{
w->depth --;
vg_kv_write_indent( w );
- fputc( '}', w->fp );
- fputc( '\n', w->fp );
+ vg_stream_write( w->stream, (c8[]){ '}', '\n' }, 2 );
}
void vg_kv_write_kv( vg_kv_write *w, const c8 *key, u32 key_len, const c8 *value, u32 value_len )
{
vg_kv_write_indent( w );
vg_kv_write_string( w, key, key_len );
- fputc( ' ', w->fp );
+ vg_stream_write( w->stream, (c8[]){ ' ' }, 1 );
vg_kv_write_string( w, value, value_len );
- fputc( '\n', w->fp );
+ vg_stream_write( w->stream, (c8[]){ '\n' }, 1 );
}
-void vg_kv_parser_print_info( vg_kv_parser *parser )
-{
- vg_low( "KV stats\n"
- " bytes pages: %u\n"
- " bytes strings: %u\n"
- " source characters: %u. compression ratio: %.2f%%\n", parser->kvs->stat_memory_pages,
- parser->stat_memory_strings,
- parser->stat_source_characters,
- (f32)(parser->stat_memory_strings+parser->kvs->stat_memory_pages) /
- (f32)parser->stat_source_characters * 100.0f );
-}
-
-void vg_kv_print_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
+void vg_kv_write_tree( vg_kv_write *w, vg_kvs *kvs, u32 root_offset )
{
if( root_offset == 0 )
root_offset = kvs->root_offset;
- VG_ASSERT( vg_kv_type( kvs, root_offset ) == 0x0 );
+ VG_ASSERT( vg_kv_type( kvs, root_offset ) == k_vg_kv_type_frame );
u32 root_len;
const c8 *root_str = vg_kv_key( kvs, root_offset, &root_len );
u32 child_offset = vg_kv_child( kvs, root_offset, 0 );
while( child_offset )
{
- if( vg_kv_type( kvs, child_offset ) == 0x0 )
- vg_kv_print_tree( w, kvs, child_offset );
+ if( vg_kv_type( kvs, child_offset ) == k_vg_kv_type_frame )
+ vg_kv_write_tree( w, kvs, child_offset );
else
{
u32 key_len;
vg_kv_end_block( w );
}
-bool vg_kv_read_vu32( vg_kvs *kvs, u32 root_offset, const c8 *key, u32 *default_value, u32 *out_value, u32 len )
-{
- bool good = 1;
- vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
- for( u32 i=0; i<len; i ++ )
- {
- u64 value = 0;
- if( vg_strp_u64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (u32)value;
- else
- {
- good = 0;
- if( default_value ) out_value[ i ] = default_value[ i ];
- else out_value[ i ] = 0;
- }
- }
- return good;
-}
-
-bool vg_kv_read_vf32( vg_kvs *kvs, u32 root_offset, const c8 *key, f32 *default_value, f32 *out_value, u32 len )
-{
- bool good = 1;
- vg_strp s = { .buffer = vg_kv_value( kvs, vg_kv_find( kvs, root_offset, key ), NULL ) };
- for( u32 i=0; i<len; i ++ )
- {
- f64 value = 0.0;
- if( vg_strp_f64( &s, &value ) == k_vg_strp_ok ) out_value[ i ] = (f32)value;
- else
- {
- good = 0;
- if( default_value ) out_value[ i ] = default_value[ i ];
- else out_value[ i ] = 0.0f;
- }
- }
- return good;
-}
-
-u32 vg_kv_append_vu32( vg_kvs *kvs, u32 parent_offset, const c8 *key, u32 *values, u32 len )
+bool vg_kv_read_file( vg_kvs *kvs, const c8 *path, vg_stack_allocator *stack )
{
- c8 formatted[ 1024 ];
- vg_str value_str;
- vg_strnull( &value_str, formatted, sizeof(formatted) );
-
- for( u32 i=0; i<len; i++ )
+ vg_stream stream;
+ if( vg_file_stream_open( &stream, path, VG_STREAM_READ ) )
{
- vg_strcatu64( &value_str, values[i], 10 );
- if( i+1!=len )
- vg_strcatch( &value_str, ' ' );
+ vg_kvs_init( kvs, stack );
+ vg_kv_parser parser;
+ vg_kv_parser_init( &parser, kvs, 0 );
+ vg_kv_parse_stream( &parser, &stream );
+ vg_file_stream_close( &stream );
+ return 1;
}
-
- if( !vg_strgood( &value_str ) )
- return 0;
-
- return vg_kv_append( kvs, parent_offset, key, formatted );
+ else return 0;
}
-u32 vg_kv_append_vf32( vg_kvs *kvs, u32 parent_offset, const c8 *key, f32 *values, u32 len )
+bool vg_kv_write_file( vg_kvs *kvs, const c8 *path )
{
- c8 formatted[ 1024 ];
- vg_str value_str;
- vg_strnull( &value_str, formatted, sizeof(formatted) );
-
- for( u32 i=0; i<len; i++ )
+ vg_stream stream;
+ if( vg_file_stream_open( &stream, path, VG_STREAM_WRITE ) )
{
- vg_strcatf64( &value_str, values[i], 10, 5 );
- if( i+1!=len )
- vg_strcatch( &value_str, ' ' );
+ vg_kv_write writer;
+ vg_kv_write_init( &writer, &stream );
+ vg_kv_write_tree( &writer, kvs, 0 );
+ vg_file_stream_close( &stream );
+ return 1;
}
-
- if( !vg_strgood( &value_str ) )
- return 0;
-
- return vg_kv_append( kvs, parent_offset, key, formatted );
+ else return 0;
}