1 #define vdf_foreach( NODE, STR, AS ) \
2 int __vdf_it_##__LINE__ = 0; \
4 while( (AS = vdf_next( NODE, STR, &__vdf_it_##__LINE__ )) )
6 #define kv_foreach( NODE, STR, AS ) \
7 int __kv_it_##__LINE__ = 0; \
9 while( (AS = kv_iter( NODE, STR, &__kv_it_##__LINE__ )) )
17 // ==================================================================================================================
19 typedef struct vdf_kv vdf_kv
;
20 typedef struct vdf_node vdf_node
;
21 typedef struct vdf_ctx vdf_ctx
;
24 // ==================================================================================================================
27 vdf_node
*vdf_open_file( const char *fn
);
28 void vdf_free_r( vdf_node
*p
);
33 // Starting from *it, get next child with matching name from node.
34 vdf_node
*vdf_next( vdf_node
*node
, const char *name
, int *it
);
36 // Create new empty node attached to parent. name can be NULL
37 vdf_node
*vdf_create_node( vdf_node
*parent
, const char *name
);
42 void vdf_out( vdf_node
*h
, int lvl
, int declare
, FILE *file
);
43 void vdf_save( vdf_node
*node
, const char *fn
);
44 void vdf_print( vdf_node
*node
);
49 // Get value string pointer from node's dictionary
50 const char *kv_get( vdf_node
*node
, const char *key
, const char *value_defalt
);
52 // Iterate each keyvalue starting from *it until key is matched
53 char *kv_iter( vdf_node
*node
, const char *key
, int *it
);
55 // Get keyvalue from node as int / float
56 int kv_get_int( vdf_node
*node
, const char *key
, const int default_value
);
57 float kv_get_float( vdf_node
*node
, const char *key
, float default_value
);
59 // Parse values into sepecifc type
60 void kv_int_array( vdf_node
*node
, const char *key
, u32 count
, int *arr
);
61 void kv_float_array( vdf_node
*node
, const char *key
, u32 count
, float *arr
);
62 void kv_double_array( vdf_node
*node
, const char *key
, u32 count
, double *arr
);
65 // ==================================================================================================================
67 // Add keyvalue pair to node
68 void vdf_kv_append( vdf_node
*p
, const char *k
, const char *v
);
70 // (low level api for arrays)
71 void kv_parse_array( const char *source
, u32 esize
, u32 count
, void(*interp_func
)(const char *src
, void *dest
), void *arr
);
72 void vdf_str_to_float( const char *src
, void *dest
);
73 void vdf_str_to_int( const char *src
, void *dest
);
77 void vdf_newln( vdf_ctx
*ctx
);
78 void vdf_endl( vdf_ctx
*ctx
);
79 int vdf_line_control( vdf_ctx
*ctx
);
80 void vdf_wait_endl( vdf_ctx
*ctx
);
81 void vdf_parse_string( vdf_ctx
*ctx
);
82 int vdf_parse_structure( vdf_ctx
*ctx
);
83 void vdf_parse_begin_token( vdf_ctx
*ctx
, char *ptr
);
84 void vdf_parse_feedbuffer( vdf_ctx
*ctx
, char *buf
);
87 void vdf_out_indent( const int n
, FILE *file
);
90 // ==================================================================================================================
110 vdf_node
*vdf_next( vdf_node
*node
, const char *name
, int *it
)
115 for( int i
= it
? *it
: 0; i
< csr_sb_count( node
->nodes
); i
++ )
117 if( !name
|| !strcmp( name
, node
->nodes
[i
]->name
))
120 return node
->nodes
[i
];
127 const char *kv_get( vdf_node
*node
, const char *key
, const char *value_defalt
)
131 for( int i
= 0; i
< csr_sb_count( node
->pairs
); i
++ )
133 if( !strcmp( node
->pairs
[ i
].key
, key
) )
135 return node
->pairs
[ i
].value
;
143 char *kv_iter( vdf_node
*node
, const char *key
, int *it
)
149 while( *it
< csr_sb_count( node
->pairs
) )
151 if( !strcmp( node
->pairs
[ *it
].key
, key
) )
153 val
= node
->pairs
[ *it
].value
;
165 void vdf_str_to_int( const char *src
, void *dest
)
167 *((int *)dest
) = atoi( src
);
170 void vdf_str_to_float( const char *src
, void *dest
)
172 *((float *)dest
) = atof( src
);
175 void vdf_str_to_double( const char *src
, void *dest
)
177 *((double *)dest
) = atof( src
);
180 void kv_parse_array( const char *source
, u32 esize
, u32 count
, void(*interp_func
)(const char *src
, void *dest
), void *arr
)
185 char value_buf
[ 64 ];
191 char const *c
= source
;
195 if( *c
== ' ' || *c
== '\t' || *c
== '[' || *c
== ']' || *c
== '(' || *c
== ')' )
199 value_buf
[ k
] = 0x00;
202 interp_func( value_buf
, ((u8
*)arr
) + i
*esize
);
221 if( k
< sizeof( value_buf
) - 1 )
223 value_buf
[ k
++ ] = *c
;
231 // Add remaining case if we hit null
232 if( token
&& (i
< count
) )
234 value_buf
[ k
] = 0x00;
235 interp_func( value_buf
, ((u8
*)arr
) + i
*esize
);
239 void kv_int_array( vdf_node
*node
, const char *key
, u32 count
, int *arr
)
241 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(int), count
, vdf_str_to_int
, arr
);
244 void kv_float_array( vdf_node
*node
, const char *key
, u32 count
, float *arr
)
246 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(float), count
, vdf_str_to_float
, arr
);
249 void kv_double_array( vdf_node
*node
, const char *key
, u32 count
, double *arr
)
251 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(double), count
, vdf_str_to_double
, arr
);
254 int kv_get_int( vdf_node
*node
, const char *key
, const int default_value
)
256 const char *v
= kv_get( node
, key
, NULL
);
257 return v
? atoi(v
): default_value
;
260 float kv_get_float( vdf_node
*node
, const char *key
, float default_value
)
262 const char *v
= kv_get( node
, key
, NULL
);
263 return v
? atof( v
): default_value
;
266 vdf_node
*vdf_create_node( vdf_node
*parent
, const char *name
)
268 vdf_node
*node
= calloc( 1, sizeof( vdf_node
) );
272 node
->name
= csr_malloc( strlen( name
)+1 );
273 strcpy( node
->name
, name
);
278 node
->parent
= parent
;
280 parent
->nodes
= csr_sb_reserve( parent
->nodes
, 1, sizeof(vdf_node
*) );
282 vdf_node
**child
= (vdf_node
**)csr_sb_use( parent
->nodes
);
289 void vdf_kv_append( vdf_node
*p
, const char *k
, const char *v
)
291 p
->pairs
= csr_sb_reserve( p
->pairs
, 1, sizeof(vdf_kv
) );
292 vdf_kv
*kv
= (vdf_kv
*)csr_sb_use( p
->pairs
);
294 u32 sv
= strlen(v
)+1;
295 u32 sk
= strlen(k
)+1;
297 kv
->key
= csr_malloc( sv
+sk
);
298 kv
->value
= kv
->key
+sk
;
300 memcpy( kv
->key
, k
, sk
);
301 memcpy( kv
->value
, v
, sv
);
304 void vdf_free_r( vdf_node
*p
)
306 for( int i
= 0; i
< csr_sb_count( p
->pairs
); i
++ )
308 free( p
->pairs
[ i
].key
);
311 for( int i
= 0; i
< csr_sb_count( p
->nodes
); i
++ )
313 vdf_free_r( p
->nodes
[ i
] );
316 csr_sb_free( p
->pairs
);
317 csr_sb_free( p
->nodes
);
323 // ==================================================================================================================
350 void vdf_newln( vdf_ctx
*ctx
)
354 ctx
->st
.tokens
[0] = NULL
;
355 ctx
->st
.tokens
[1] = NULL
;
359 void vdf_endl( vdf_ctx
*ctx
)
362 if( ctx
->st
.tokens
[0] )
365 if( ctx
->st
.tokens
[1] )
367 vdf_kv_append( ctx
->st
.pnode
, ctx
->st
.tokens
[0], ctx
->st
.tokens
[1] );
372 strcpy( ctx
->name
, ctx
->st
.tokens
[0] );
373 ctx
->st
.expect_decl
= 1;
380 int vdf_line_control( vdf_ctx
*ctx
)
382 if( *ctx
->st
.ptr_read
== '\r' )
384 *ctx
->st
.ptr_read
= 0x00;
387 if( *ctx
->st
.ptr_read
== '\n' )
389 *ctx
->st
.ptr_read
= 0x00;
397 void vdf_wait_endl( vdf_ctx
*ctx
)
399 while( (*ctx
->st
.ptr_read
) && (*ctx
->st
.ptr_read
!= '\n') )
401 if( vdf_line_control( ctx
) == 2 )
410 void vdf_parse_string( vdf_ctx
*ctx
)
412 while( *ctx
->st
.ptr_read
)
414 if( *ctx
->st
.ptr_read
== '"' )
416 *ctx
->st
.ptr_read
= 0x00;
420 if( vdf_line_control( ctx
) )
422 fprintf( stderr
, "Unexpected end of line character (Line: %u)\n", ctx
->lines
);
430 int vdf_parse_structure( vdf_ctx
*ctx
)
432 if( *ctx
->st
.ptr_read
== '{' )
434 if( ctx
->st
.tokens
[0] || !ctx
->st
.expect_decl
)
436 fprintf( stderr
, "Unexpected token '{' (Line: %u)\n", ctx
->lines
);
440 ctx
->st
.expect_decl
= 0;
441 ctx
->st
.pnode
= vdf_create_node( ctx
->st
.pnode
, ctx
->name
);
443 vdf_wait_endl( ctx
);
447 // Closing block, jump read head back to parent
448 if( *ctx
->st
.ptr_read
== '}' )
450 if( !ctx
->st
.pnode
->parent
)
452 fprintf( stderr
, "Unexpected token '}' (Line: %u)\n", ctx
->lines
);
457 ctx
->st
.pnode
= ctx
->st
.pnode
->parent
;
460 vdf_wait_endl( ctx
);
467 void vdf_parse_begin_token( vdf_ctx
*ctx
, char *ptr
)
469 ctx
->st
.tokens
[ ctx
->st
.i
] = ptr
;
471 if( ctx
->st
.expect_decl
)
473 fprintf( stderr
, "Unexpected token '%s' (Line: %u)\n", ctx
->name
, ctx
->lines
);
478 void vdf_parse_feedbuffer( vdf_ctx
*ctx
, char *buf
)
480 ctx
->st
.ptr_read
= buf
;
482 while( *ctx
->st
.ptr_read
)
484 if( !vdf_line_control( ctx
) )
486 if( (*ctx
->st
.ptr_read
== '/') && (ctx
->st
.ptr_read
[1] == '/') )
488 *ctx
->st
.ptr_read
= 0x00;
489 ctx
->st
.ptr_read
+= 2;
492 vdf_wait_endl( ctx
);
496 if( !vdf_parse_structure( ctx
) )
498 if( *ctx
->st
.ptr_read
== ' ' || *ctx
->st
.ptr_read
== '\t' )
500 *ctx
->st
.ptr_read
= 0x00;
502 if( ctx
->st
.tokens
[ ctx
->st
.i
] )
508 vdf_wait_endl( ctx
);
513 else if( !ctx
->st
.tokens
[ ctx
->st
.i
] )
515 if( *ctx
->st
.ptr_read
== '"' )
517 *ctx
->st
.ptr_read
= 0x00;
520 vdf_parse_begin_token( ctx
, ctx
->st
.ptr_read
);
521 vdf_parse_string( ctx
);
525 if( !( *ctx
->st
.ptr_read
== '/' && *(ctx
->st
.ptr_read
+ 1) == *ctx
->st
.ptr_read
) )
527 vdf_parse_begin_token( ctx
, ctx
->st
.ptr_read
);
539 int vdf_load_into( const char *fn
, vdf_node
*node
)
541 char *text_src
= csr_textasset_read( fn
);
545 fprintf( stderr
, "vdf open failed\n" );
550 ctx
.root
= ctx
.st
.pnode
= node
;
553 vdf_parse_feedbuffer( &ctx
, text_src
);
559 vdf_node
*vdf_open_file( const char *fn
)
561 vdf_node
*root
= vdf_create_node( NULL
, NULL
);
562 if( vdf_load_into( fn
, root
) )
574 // ==================================================================================================================
576 void vdf_out_indent( const int n
, FILE *file
)
578 for( int x
= 0; x
< n
; x
++ )
579 fprintf( file
, "\t" );
582 void vdf_out( vdf_node
*h
, int lvl
, int declare
, FILE *file
)
586 vdf_out_indent( lvl
, file
); fprintf( file
, "\"%s\"\n", h
->name
);
587 vdf_out_indent( lvl
, file
); fprintf( file
, "{\n" );
590 for( int i
= 0; i
< csr_sb_count( h
->pairs
); i
++ )
592 vdf_out_indent( lvl
+1, file
); fprintf( file
, "\"%s\" \"%s\"\n", h
->pairs
[i
].key
, h
->pairs
[i
].value
);
595 for( int i
= 0; i
< csr_sb_count( h
->nodes
); i
++ )
597 vdf_out( h
->nodes
[i
], lvl
+ 1, 1, file
);
602 vdf_out_indent( lvl
, file
); fprintf( file
, "}\n" );
606 void vdf_save( vdf_node
*node
, const char *fn
)
608 FILE* file
= fopen( fn
, "w" );
610 vdf_out( node
, -1, 0, file
);
615 void vdf_print( vdf_node
*node
)
617 vdf_out( node
, -1, 0, stdout
);