vpk loading/models
[csRadar.git] / vdf.h
1 #define vdf_foreach( NODE, STR, AS ) \
2 int __vdf_it_##__LINE__ = 0; \
3 vdf_node * AS;\
4 while( (AS = vdf_next( NODE, STR, &__vdf_it_##__LINE__ )) )
5
6 #define kv_foreach( NODE, STR, AS ) \
7 int __kv_it_##__LINE__ = 0; \
8 const char * AS;\
9 while( (AS = kv_iter( NODE, STR, &__kv_it_##__LINE__ )) )
10
11 #include <stdio.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 // TYPES
17 // ==================================================================================================================
18
19 typedef struct vdf_kv vdf_kv;
20 typedef struct vdf_node vdf_node;
21 typedef struct vdf_ctx vdf_ctx;
22
23 // API
24 // ==================================================================================================================
25
26 // Open / close
27 vdf_node *vdf_open_file( const char *fn );
28 void vdf_free_r( vdf_node *p );
29
30 // Nodes
31 // -----
32
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 );
35
36 // Create new empty node attached to parent. name can be NULL
37 vdf_node *vdf_create_node( vdf_node *parent, const char *name );
38
39 // Save / printing
40 // ---------------
41
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 );
45
46 // Keyvalue pairs
47 // --------------
48
49 // Get value string pointer from node's dictionary
50 const char *kv_get( vdf_node *node, const char *key, const char *value_defalt );
51
52 // Iterate each keyvalue starting from *it until key is matched
53 char *kv_iter( vdf_node *node, const char *key, int *it );
54
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 );
58
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 );
63
64 // INTERNAL API
65 // ==================================================================================================================
66
67 // Add keyvalue pair to node
68 void vdf_kv_append( vdf_node *p, const char *k, const char *v );
69
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 );
74
75 // Parsing context
76 // ---------------
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 );
85
86 // Formatting
87 void vdf_out_indent( const int n, FILE *file );
88
89 // IMPLEMENTATION
90 // ==================================================================================================================
91
92 struct vdf_kv
93 {
94 char *key;
95 char *value;
96 };
97
98 struct vdf_node
99 {
100 char *name;
101
102 vdf_node *parent;
103
104 vdf_node **nodes;
105 vdf_kv *pairs;
106
107 u32 user;
108 };
109
110 vdf_node *vdf_next( vdf_node *node, const char *name, int *it )
111 {
112 if( !node )
113 return NULL;
114
115 for( int i = it? *it: 0; i < csr_sb_count( node->nodes ); i ++ )
116 {
117 if( !name || !strcmp( name, node->nodes[i]->name ))
118 {
119 if( it ) *it = i+1;
120 return node->nodes[i];
121 }
122 }
123
124 return NULL;
125 }
126
127 const char *kv_get( vdf_node *node, const char *key, const char *value_defalt )
128 {
129 if( node )
130 {
131 for( int i = 0; i < csr_sb_count( node->pairs ); i ++ )
132 {
133 if( !strcmp( node->pairs[ i ].key, key ) )
134 {
135 return node->pairs[ i ].value;
136 }
137 }
138 }
139
140 return value_defalt;
141 }
142
143 char *kv_iter( vdf_node *node, const char *key, int *it )
144 {
145 char *val;
146
147 if( node )
148 {
149 while( *it < csr_sb_count( node->pairs ) )
150 {
151 if( !strcmp( node->pairs[ *it ].key, key ) )
152 {
153 val = node->pairs[ *it ].value;
154 *it = *it + 1;
155 return val;
156 }
157
158 *it = *it + 1;
159 }
160 }
161
162 return NULL;
163 }
164
165 void vdf_str_to_int( const char *src, void *dest )
166 {
167 *((int *)dest) = atoi( src );
168 }
169
170 void vdf_str_to_float( const char *src, void *dest )
171 {
172 *((float *)dest) = atof( src );
173 }
174
175 void vdf_str_to_double( const char *src, void *dest )
176 {
177 *((double *)dest) = atof( src );
178 }
179
180 void kv_parse_array( const char *source, u32 esize, u32 count, void(*interp_func)(const char *src, void *dest), void *arr )
181 {
182 if( !source )
183 return;
184
185 char value_buf[ 64 ];
186 int token = 0;
187
188 u32 i = 0;
189 u32 k = 0;
190
191 char const *c = source;
192
193 while( *c )
194 {
195 if( *c == ' ' || *c == '\t' || *c == '[' || *c == ']' || *c == '(' || *c == ')' )
196 {
197 if( token )
198 {
199 value_buf[ k ] = 0x00;
200 token = 0;
201
202 interp_func( value_buf, ((u8 *)arr) + i*esize );
203 i ++;
204
205 if( i >= count )
206 {
207 break;
208 }
209 }
210 }
211 else
212 {
213 if( !token )
214 {
215 token = 1;
216 k = 0;
217 }
218
219 if( token )
220 {
221 if( k < sizeof( value_buf ) - 1 )
222 {
223 value_buf[ k ++ ] = *c;
224 }
225 }
226 }
227
228 c ++;
229 }
230
231 // Add remaining case if we hit null
232 if( token && (i < count) )
233 {
234 value_buf[ k ] = 0x00;
235 interp_func( value_buf, ((u8 *)arr) + i*esize );
236 }
237 }
238
239 void kv_int_array( vdf_node *node, const char *key, u32 count, int *arr )
240 {
241 kv_parse_array( kv_get( node, key, NULL ), sizeof(int), count, vdf_str_to_int, arr );
242 }
243
244 void kv_float_array( vdf_node *node, const char *key, u32 count, float *arr )
245 {
246 kv_parse_array( kv_get( node, key, NULL ), sizeof(float), count, vdf_str_to_float, arr );
247 }
248
249 void kv_double_array( vdf_node *node, const char *key, u32 count, double *arr )
250 {
251 kv_parse_array( kv_get( node, key, NULL ), sizeof(double), count, vdf_str_to_double, arr );
252 }
253
254 int kv_get_int( vdf_node *node, const char *key, const int default_value )
255 {
256 const char *v = kv_get( node, key, NULL );
257 return v? atoi(v): default_value;
258 }
259
260 float kv_get_float( vdf_node *node, const char *key, float default_value )
261 {
262 const char *v = kv_get( node, key, NULL );
263 return v? atof( v ): default_value;
264 }
265
266 vdf_node *vdf_create_node( vdf_node *parent, const char *name )
267 {
268 vdf_node *node = calloc( 1, sizeof( vdf_node ) );
269
270 if( name )
271 {
272 node->name = csr_malloc( strlen( name )+1 );
273 strcpy( node->name, name );
274 }
275
276 if( parent )
277 {
278 node->parent = parent;
279
280 parent->nodes = csr_sb_reserve( parent->nodes, 1, sizeof(vdf_node *) );
281
282 vdf_node **child = (vdf_node **)csr_sb_use( parent->nodes );
283 *child = node;
284 }
285
286 return node;
287 }
288
289 void vdf_kv_append( vdf_node *p, const char *k, const char *v )
290 {
291 p->pairs = csr_sb_reserve( p->pairs, 1, sizeof(vdf_kv) );
292 vdf_kv *kv = (vdf_kv *)csr_sb_use( p->pairs );
293
294 u32 sv = strlen(v)+1;
295 u32 sk = strlen(k)+1;
296
297 kv->key = csr_malloc( sv+sk );
298 kv->value = kv->key+sk;
299
300 memcpy( kv->key, k, sk );
301 memcpy( kv->value, v, sv );
302 }
303
304 void vdf_free_r( vdf_node *p )
305 {
306 for( int i = 0; i < csr_sb_count( p->pairs ); i ++ )
307 {
308 free( p->pairs[ i ].key );
309 }
310
311 for( int i = 0; i < csr_sb_count( p->nodes ); i ++ )
312 {
313 vdf_free_r( p->nodes[ i ] );
314 }
315
316 csr_sb_free( p->pairs );
317 csr_sb_free( p->nodes );
318 free( p->name );
319 free( p );
320 }
321
322 // PARSING
323 // ==================================================================================================================
324
325 struct vdf_ctx
326 {
327 char name[2048];
328
329 vdf_node *root;
330
331 u32 lines;
332 u32 errors;
333
334 // State
335 struct
336 {
337 int wait;
338 int expect_decl;
339
340 char *tokens[2];
341 int i;
342
343 char *ptr_read;
344
345 vdf_node *pnode;
346 }
347 st;
348 };
349
350 void vdf_newln( vdf_ctx *ctx )
351 {
352 ctx->lines ++;
353
354 ctx->st.tokens[0] = NULL;
355 ctx->st.tokens[1] = NULL;
356 ctx->st.i = 0;
357 }
358
359 void vdf_endl( vdf_ctx *ctx )
360 {
361 // Final out-tokens
362 if( ctx->st.tokens[0] )
363 {
364 // Keypair
365 if( ctx->st.tokens[1] )
366 {
367 vdf_kv_append( ctx->st.pnode, ctx->st.tokens[0], ctx->st.tokens[1] );
368 }
369 else
370 {
371 // Decl
372 strcpy( ctx->name, ctx->st.tokens[0] );
373 ctx->st.expect_decl = 1;
374 }
375 }
376
377 vdf_newln( ctx );
378 }
379
380 int vdf_line_control( vdf_ctx *ctx )
381 {
382 if( *ctx->st.ptr_read == '\r' )
383 {
384 *ctx->st.ptr_read = 0x00;
385 return 1;
386 }
387 if( *ctx->st.ptr_read == '\n' )
388 {
389 *ctx->st.ptr_read = 0x00;
390 vdf_endl( ctx );
391 return 2;
392 }
393
394 return 0;
395 }
396
397 void vdf_wait_endl( vdf_ctx *ctx )
398 {
399 while( (*ctx->st.ptr_read) && (*ctx->st.ptr_read != '\n') )
400 {
401 if( vdf_line_control( ctx ) == 2 )
402 {
403 return;
404 }
405
406 ctx->st.ptr_read ++;
407 }
408 }
409
410 void vdf_parse_string( vdf_ctx *ctx )
411 {
412 while( *ctx->st.ptr_read )
413 {
414 if( *ctx->st.ptr_read == '"' )
415 {
416 *ctx->st.ptr_read = 0x00;
417 return;
418 }
419
420 if( vdf_line_control( ctx ) )
421 {
422 fprintf( stderr, "Unexpected end of line character (Line: %u)\n", ctx->lines );
423 return;
424 }
425
426 ctx->st.ptr_read ++;
427 }
428 }
429
430 int vdf_parse_structure( vdf_ctx *ctx )
431 {
432 if( *ctx->st.ptr_read == '{' )
433 {
434 if( ctx->st.tokens[0] || !ctx->st.expect_decl )
435 {
436 fprintf( stderr, "Unexpected token '{' (Line: %u)\n", ctx->lines );
437 ctx->errors ++;
438 }
439
440 ctx->st.expect_decl = 0;
441 ctx->st.pnode = vdf_create_node( ctx->st.pnode, ctx->name );
442
443 vdf_wait_endl( ctx );
444 return 1;
445 }
446
447 // Closing block, jump read head back to parent
448 if( *ctx->st.ptr_read == '}' )
449 {
450 if( !ctx->st.pnode->parent )
451 {
452 fprintf( stderr, "Unexpected token '}' (Line: %u)\n", ctx->lines );
453 ctx->errors ++;
454 }
455 else
456 {
457 ctx->st.pnode = ctx->st.pnode->parent;
458 }
459
460 vdf_wait_endl( ctx );
461 return 1;
462 }
463
464 return 0;
465 }
466
467 void vdf_parse_begin_token( vdf_ctx *ctx, char *ptr )
468 {
469 ctx->st.tokens[ ctx->st.i ] = ptr;
470
471 if( ctx->st.expect_decl )
472 {
473 fprintf( stderr, "Unexpected token '%s' (Line: %u)\n", ctx->name, ctx->lines );
474 ctx->errors ++;
475 }
476 }
477
478 void vdf_parse_feedbuffer( vdf_ctx *ctx, char *buf )
479 {
480 ctx->st.ptr_read = buf;
481
482 while( *ctx->st.ptr_read )
483 {
484 if( !vdf_line_control( ctx ) )
485 {
486 if( (*ctx->st.ptr_read == '/') && (ctx->st.ptr_read[1] == '/') )
487 {
488 *ctx->st.ptr_read = 0x00;
489 ctx->st.ptr_read += 2;
490
491 vdf_endl( ctx );
492 vdf_wait_endl( ctx );
493 }
494 else
495 {
496 if( !vdf_parse_structure( ctx ) )
497 {
498 if( *ctx->st.ptr_read == ' ' || *ctx->st.ptr_read == '\t' )
499 {
500 *ctx->st.ptr_read = 0x00;
501
502 if( ctx->st.tokens[ ctx->st.i ] )
503 {
504 ctx->st.i ++;
505
506 if( ctx->st.i == 2 )
507 {
508 vdf_wait_endl( ctx );
509 }
510 }
511 }
512 // Start new entry
513 else if( !ctx->st.tokens[ ctx->st.i ] )
514 {
515 if( *ctx->st.ptr_read == '"' )
516 {
517 *ctx->st.ptr_read = 0x00;
518 ctx->st.ptr_read ++;
519
520 vdf_parse_begin_token( ctx, ctx->st.ptr_read );
521 vdf_parse_string( ctx );
522 }
523 else
524 {
525 if( !( *ctx->st.ptr_read == '/' && *(ctx->st.ptr_read + 1) == *ctx->st.ptr_read ) )
526 {
527 vdf_parse_begin_token( ctx, ctx->st.ptr_read );
528 }
529 }
530 }
531 }
532 }
533 }
534
535 ctx->st.ptr_read ++;
536 }
537 }
538
539 int vdf_load_into( const char *fn, vdf_node *node )
540 {
541 char *text_src = csr_textasset_read( fn );
542
543 if( !text_src )
544 {
545 fprintf( stderr, "vdf open failed\n" );
546 return 0;
547 }
548
549 vdf_ctx ctx = {0};
550 ctx.root = ctx.st.pnode = node;
551
552 vdf_newln( &ctx );
553 vdf_parse_feedbuffer( &ctx, text_src );
554 free( text_src );
555
556 return 1;
557 }
558
559 vdf_node *vdf_open_file( const char *fn )
560 {
561 vdf_node *root = vdf_create_node( NULL, NULL );
562 if( vdf_load_into( fn, root ) )
563 {
564 return root;
565 }
566 else
567 {
568 vdf_free_r( root );
569 return NULL;
570 }
571 }
572
573 // OUTPUT
574 // ==================================================================================================================
575
576 void vdf_out_indent( const int n, FILE *file )
577 {
578 for( int x = 0; x < n; x ++ )
579 fprintf( file, "\t" );
580 }
581
582 void vdf_out( vdf_node *h, int lvl, int declare, FILE *file )
583 {
584 if( declare )
585 {
586 vdf_out_indent( lvl, file ); fprintf( file, "\"%s\"\n", h->name );
587 vdf_out_indent( lvl, file ); fprintf( file, "{\n" );
588 }
589
590 for( int i = 0; i < csr_sb_count( h->pairs ); i ++ )
591 {
592 vdf_out_indent( lvl+1, file ); fprintf( file, "\"%s\" \"%s\"\n", h->pairs[i].key, h->pairs[i].value );
593 }
594
595 for( int i = 0; i < csr_sb_count( h->nodes ); i ++ )
596 {
597 vdf_out( h->nodes[i], lvl + 1, 1, file );
598 }
599
600 if( declare )
601 {
602 vdf_out_indent( lvl, file ); fprintf( file, "}\n" );
603 }
604 }
605
606 void vdf_save( vdf_node *node, const char *fn )
607 {
608 FILE* file = fopen( fn, "w" );
609
610 vdf_out( node, -1, 0, file );
611
612 fclose( file );
613 }
614
615 void vdf_print( vdf_node *node )
616 {
617 vdf_out( node, -1, 0, stdout );
618 }