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