892b65d5f304386a0efa532888e14c79398c20ca
1 #define vdf_foreach( NODE, STR, AS ) \
2 int __vdf_it_##AS = 0; \
4 while( (AS = vdf_next( NODE, STR, &__vdf_it_##AS )) )
6 #define kv_foreach( NODE, STR, AS ) \
7 int __kv_it_##AS = 0; \
9 while( (AS = kv_iter( NODE, STR, &__kv_it_##AS )) )
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 // ==================================================================================================================
111 vdf_node
*vdf_next( vdf_node
*node
, const char *name
, int *it
)
116 for( int i
= it
? *it
: 0; i
< csr_sb_count( node
->nodes
); i
++ )
118 if( !name
|| !strcmp( name
, node
->nodes
[i
]->name
))
121 return node
->nodes
[i
];
128 const char *kv_get( vdf_node
*node
, const char *key
, const char *value_defalt
)
132 for( int i
= 0; i
< csr_sb_count( node
->pairs
); i
++ )
134 if( !strcmp( node
->pairs
[ i
].key
, key
) )
136 return node
->pairs
[ i
].value
;
144 char *kv_iter( vdf_node
*node
, const char *key
, int *it
)
150 while( *it
< csr_sb_count( node
->pairs
) )
152 if( !strcmp( node
->pairs
[ *it
].key
, key
) )
154 val
= node
->pairs
[ *it
].value
;
166 void vdf_str_to_int( const char *src
, void *dest
)
168 *((int *)dest
) = atoi( src
);
171 void vdf_str_to_float( const char *src
, void *dest
)
173 *((float *)dest
) = atof( src
);
176 void vdf_str_to_double( const char *src
, void *dest
)
178 *((double *)dest
) = atof( src
);
181 void kv_parse_array( const char *source
, u32 esize
, u32 count
, void(*interp_func
)(const char *src
, void *dest
), void *arr
)
186 char value_buf
[ 64 ];
192 char const *c
= source
;
196 if( *c
== ' ' || *c
== '\t' || *c
== '[' || *c
== ']' || *c
== '(' || *c
== ')' )
200 value_buf
[ k
] = 0x00;
203 interp_func( value_buf
, ((u8
*)arr
) + i
*esize
);
222 if( k
< sizeof( value_buf
) - 1 )
224 value_buf
[ k
++ ] = *c
;
232 // Add remaining case if we hit null
233 if( token
&& (i
< count
) )
235 value_buf
[ k
] = 0x00;
236 interp_func( value_buf
, ((u8
*)arr
) + i
*esize
);
240 void kv_int_array( vdf_node
*node
, const char *key
, u32 count
, int *arr
)
242 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(int), count
, vdf_str_to_int
, arr
);
245 void kv_float_array( vdf_node
*node
, const char *key
, u32 count
, float *arr
)
247 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(float), count
, vdf_str_to_float
, arr
);
250 void kv_double_array( vdf_node
*node
, const char *key
, u32 count
, double *arr
)
252 kv_parse_array( kv_get( node
, key
, NULL
), sizeof(double), count
, vdf_str_to_double
, arr
);
255 int kv_get_int( vdf_node
*node
, const char *key
, const int default_value
)
257 const char *v
= kv_get( node
, key
, NULL
);
258 return v
? atoi(v
): default_value
;
261 float kv_get_float( vdf_node
*node
, const char *key
, float default_value
)
263 const char *v
= kv_get( node
, key
, NULL
);
264 return v
? atof( v
): default_value
;
267 vdf_node
*vdf_create_node( vdf_node
*parent
, const char *name
)
269 vdf_node
*node
= calloc( 1, sizeof( vdf_node
) );
273 node
->name
= csr_malloc( strlen( name
)+1 );
274 strcpy( node
->name
, name
);
279 node
->parent
= parent
;
281 parent
->nodes
= csr_sb_reserve( parent
->nodes
, 1, sizeof(vdf_node
*) );
283 vdf_node
**child
= (vdf_node
**)csr_sb_use( parent
->nodes
);
290 void vdf_kv_append( vdf_node
*p
, const char *k
, const char *v
)
292 p
->pairs
= csr_sb_reserve( p
->pairs
, 1, sizeof(vdf_kv
) );
293 vdf_kv
*kv
= (vdf_kv
*)csr_sb_use( p
->pairs
);
295 u32 sv
= strlen(v
)+1;
296 u32 sk
= strlen(k
)+1;
298 kv
->key
= csr_malloc( sv
+sk
);
299 kv
->value
= kv
->key
+sk
;
301 memcpy( kv
->key
, k
, sk
);
302 memcpy( kv
->value
, v
, sv
);
305 void vdf_free_r( vdf_node
*p
)
307 for( int i
= 0; i
< csr_sb_count( p
->pairs
); i
++ )
309 free( p
->pairs
[ i
].key
);
312 for( int i
= 0; i
< csr_sb_count( p
->nodes
); i
++ )
314 vdf_free_r( p
->nodes
[ i
] );
317 csr_sb_free( p
->pairs
);
318 csr_sb_free( p
->nodes
);
324 // ==================================================================================================================
351 void vdf_newln( vdf_ctx
*ctx
)
355 ctx
->st
.tokens
[0] = NULL
;
356 ctx
->st
.tokens
[1] = NULL
;
360 void vdf_endl( vdf_ctx
*ctx
)
363 if( ctx
->st
.tokens
[0] )
366 if( ctx
->st
.tokens
[1] )
368 vdf_kv_append( ctx
->st
.pnode
, ctx
->st
.tokens
[0], ctx
->st
.tokens
[1] );
373 strcpy( ctx
->name
, ctx
->st
.tokens
[0] );
374 ctx
->st
.expect_decl
= 1;
381 int vdf_line_control( vdf_ctx
*ctx
)
383 if( *ctx
->st
.ptr_read
== '\r' )
385 *ctx
->st
.ptr_read
= 0x00;
388 if( *ctx
->st
.ptr_read
== '\n' )
390 *ctx
->st
.ptr_read
= 0x00;
398 void vdf_wait_endl( vdf_ctx
*ctx
)
400 while( (*ctx
->st
.ptr_read
) && (*ctx
->st
.ptr_read
!= '\n') )
402 if( vdf_line_control( ctx
) == 2 )
411 void vdf_parse_string( vdf_ctx
*ctx
)
413 while( *ctx
->st
.ptr_read
)
415 if( *ctx
->st
.ptr_read
== '"' )
417 *ctx
->st
.ptr_read
= 0x00;
421 if( vdf_line_control( ctx
) )
423 fprintf( stderr
, "Unexpected end of line character (Line: %u)\n", ctx
->lines
);
431 int vdf_parse_structure( vdf_ctx
*ctx
)
433 if( *ctx
->st
.ptr_read
== '{' )
435 if( ctx
->st
.tokens
[0] || !ctx
->st
.expect_decl
)
437 fprintf( stderr
, "Unexpected token '{' (Line: %u)\n", ctx
->lines
);
441 ctx
->st
.expect_decl
= 0;
442 ctx
->st
.pnode
= vdf_create_node( ctx
->st
.pnode
, ctx
->name
);
444 vdf_wait_endl( ctx
);
448 // Closing block, jump read head back to parent
449 if( *ctx
->st
.ptr_read
== '}' )
451 if( !ctx
->st
.pnode
->parent
)
453 fprintf( stderr
, "Unexpected token '}' (Line: %u)\n", ctx
->lines
);
458 ctx
->st
.pnode
= ctx
->st
.pnode
->parent
;
461 vdf_wait_endl( ctx
);
468 void vdf_parse_begin_token( vdf_ctx
*ctx
, char *ptr
)
470 ctx
->st
.tokens
[ ctx
->st
.i
] = ptr
;
472 if( ctx
->st
.expect_decl
)
474 fprintf( stderr
, "Unexpected token '%s' (Line: %u)\n", ctx
->name
, ctx
->lines
);
479 void vdf_parse_feedbuffer( vdf_ctx
*ctx
, char *buf
)
481 ctx
->st
.ptr_read
= buf
;
483 while( *ctx
->st
.ptr_read
)
485 if( !vdf_line_control( ctx
) )
487 if( (*ctx
->st
.ptr_read
== '/') && (ctx
->st
.ptr_read
[1] == '/') )
489 *ctx
->st
.ptr_read
= 0x00;
490 ctx
->st
.ptr_read
+= 2;
493 vdf_wait_endl( ctx
);
497 if( !vdf_parse_structure( ctx
) )
499 if( *ctx
->st
.ptr_read
== ' ' || *ctx
->st
.ptr_read
== '\t' )
501 *ctx
->st
.ptr_read
= 0x00;
503 if( ctx
->st
.tokens
[ ctx
->st
.i
] )
509 vdf_wait_endl( ctx
);
514 else if( !ctx
->st
.tokens
[ ctx
->st
.i
] )
516 if( *ctx
->st
.ptr_read
== '"' )
518 *ctx
->st
.ptr_read
= 0x00;
521 vdf_parse_begin_token( ctx
, ctx
->st
.ptr_read
);
522 vdf_parse_string( ctx
);
526 if( !( *ctx
->st
.ptr_read
== '/' && *(ctx
->st
.ptr_read
+ 1) == *ctx
->st
.ptr_read
) )
528 vdf_parse_begin_token( ctx
, ctx
->st
.ptr_read
);
540 int vdf_load_into( const char *fn
, vdf_node
*node
)
542 char *text_src
= csr_textasset_read( fn
);
546 fprintf( stderr
, "vdf open failed\n" );
551 ctx
.root
= ctx
.st
.pnode
= node
;
554 vdf_parse_feedbuffer( &ctx
, text_src
);
560 vdf_node
*vdf_open_file( const char *fn
)
562 vdf_node
*root
= vdf_create_node( NULL
, NULL
);
563 if( vdf_load_into( fn
, root
) )
575 // ==================================================================================================================
577 void vdf_out_indent( const int n
, FILE *file
)
579 for( int x
= 0; x
< n
; x
++ )
580 fprintf( file
, "\t" );
583 void vdf_out( vdf_node
*h
, int lvl
, int declare
, FILE *file
)
587 vdf_out_indent( lvl
, file
); fprintf( file
, "\"%s\"\n", h
->name
);
588 vdf_out_indent( lvl
, file
); fprintf( file
, "{\n" );
591 for( int i
= 0; i
< csr_sb_count( h
->pairs
); i
++ )
593 vdf_out_indent( lvl
+1, file
); fprintf( file
, "\"%s\" \"%s\"\n", h
->pairs
[i
].key
, h
->pairs
[i
].value
);
596 for( int i
= 0; i
< csr_sb_count( h
->nodes
); i
++ )
598 vdf_out( h
->nodes
[i
], lvl
+ 1, 1, file
);
603 vdf_out_indent( lvl
, file
); fprintf( file
, "}\n" );
607 void vdf_save( vdf_node
*node
, const char *fn
)
609 FILE* file
= fopen( fn
, "w" );
611 vdf_out( node
, -1, 0, file
);
616 void vdf_print( vdf_node
*node
)
618 vdf_out( node
, -1, 0, stdout
);