comparison th_config.c @ 776:680324e43852

Rename a number of config parser variables etc.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 02 Jul 2023 00:43:59 +0300
parents 456235ae762e
children 484853471eaf
comparison
equal deleted inserted replaced
775:456235ae762e 776:680324e43852
197 }; 197 };
198 198
199 199
200 typedef struct 200 typedef struct
201 { 201 {
202 int ch, strDelim, 202 int ch, delim,
203 prevMode, nextMode, parseMode; 203 prev, next, mode;
204 } th_cfgparserctx_t; 204 } th_cfgparserctx_t;
205 205
206 /// @endcond 206 /// @endcond
207 207
208 208
209 static void th_cfg_set_parsemode(th_cfgparserctx_t *ctx, const int mode) 209 static void th_cfg_set_parsemode(th_cfgparserctx_t *ctx, const int mode)
210 { 210 {
211 ctx->prevMode = ctx->parseMode; 211 ctx->prev = ctx->mode;
212 ctx->parseMode = mode; 212 ctx->mode = mode;
213 } 213 }
214 214
215 215
216 static void th_cfg_set_next_parsemode(th_cfgparserctx_t *ctx, const int mode) 216 static void th_cfg_set_next_parsemode(th_cfgparserctx_t *ctx, const int mode)
217 { 217 {
218 th_cfg_set_parsemode(ctx, PM_NEXT); 218 th_cfg_set_parsemode(ctx, PM_NEXT);
219 ctx->nextMode = mode; 219 ctx->next = mode;
220 } 220 }
221 221
222 222
223 #define VADDCH(ch) if (strPos < SET_CFG_MAX_PARSE_BUF) { tmpStr[strPos++] = ch; } 223 #define VADDCH(ch) if (pos < SET_CFG_MAX_PARSE_BUF) { str[pos++] = ch; }
224 224
225 225
226 static bool th_cfg_is_end(const int ch) 226 static bool th_cfg_is_end(const int ch)
227 { 227 {
228 return 228 return
321 321
322 static int th_cfg_read_sect(th_ioctx_t *fh, th_cfgitem_t *sect, int nesting) 322 static int th_cfg_read_sect(th_ioctx_t *fh, th_cfgitem_t *sect, int nesting)
323 { 323 {
324 th_cfgparserctx_t ctx; 324 th_cfgparserctx_t ctx;
325 th_cfgitem_t *item = NULL; 325 th_cfgitem_t *item = NULL;
326 char *tmpStr = NULL; 326 char *str = NULL;
327 size_t strPos; 327 size_t pos;
328 bool isEscaped, isStart, fpSet; 328 bool escaped, start, fpseparator;
329 int ret = THERR_OK; 329 int ret = THERR_OK;
330 330
331 // Initialize values 331 // Initialize values
332 memset(&ctx, 0, sizeof(ctx)); 332 memset(&ctx, 0, sizeof(ctx));
333 ctx.ch = -1; 333 ctx.ch = -1;
334 ctx.nextMode = ctx.prevMode = ctx.parseMode = PM_IDLE; 334 ctx.next = ctx.prev = ctx.mode = PM_IDLE;
335 isEscaped = fpSet = isStart = false; 335 escaped = fpseparator = start = false;
336 strPos = 0; 336 pos = 0;
337 337
338 if ((tmpStr = th_malloc(SET_CFG_MAX_PARSE_BUF + 1)) == NULL) 338 if ((str = th_malloc(SET_CFG_MAX_PARSE_BUF + 1)) == NULL)
339 goto out; 339 goto out;
340 340
341 // Parse the configuration 341 // Parse the configuration
342 while (ctx.parseMode != PM_EOF && ctx.parseMode != PM_ERROR) 342 while (ctx.mode != PM_EOF && ctx.mode != PM_ERROR)
343 { 343 {
344 if (ctx.ch == -1) 344 if (ctx.ch == -1)
345 { 345 {
346 // Get next character 346 // Get next character
347 switch (ctx.ch = thfgetc(fh)) 347 switch (ctx.ch = thfgetc(fh))
348 { 348 {
349 case EOF: 349 case EOF:
350 if (ctx.parseMode != PM_IDLE) 350 if (ctx.mode != PM_IDLE)
351 { 351 {
352 ret = th_io_error(fh, THERR_OUT_OF_DATA, 352 ret = th_io_error(fh, THERR_OUT_OF_DATA,
353 "Unexpected end of file."); 353 "Unexpected end of file.");
354 goto out; 354 goto out;
355 } 355 }
356 356
357 ctx.parseMode = PM_EOF; 357 ctx.mode = PM_EOF;
358 break; 358 break;
359 359
360 case '\n': 360 case '\n':
361 fh->line++; 361 fh->line++;
362 } 362 }
363 } 363 }
364 364
365 switch (ctx.parseMode) 365 switch (ctx.mode)
366 { 366 {
367 case PM_COMMENT: 367 case PM_COMMENT:
368 // Comment parsing mode 368 // Comment parsing mode
369 if (ctx.ch == '\n') 369 if (ctx.ch == '\n')
370 { 370 {
371 // End of line, end of comment 371 // End of line, end of comment
372 th_cfg_set_parsemode(&ctx, ctx.prevMode); 372 th_cfg_set_parsemode(&ctx, ctx.prev);
373 } 373 }
374 ctx.ch = -1; 374 ctx.ch = -1;
375 break; 375 break;
376 376
377 case PM_IDLE: 377 case PM_IDLE:
404 else 404 else
405 if (th_isalpha(ctx.ch)) 405 if (th_isalpha(ctx.ch))
406 { 406 {
407 // Start of key name found 407 // Start of key name found
408 th_cfg_set_parsemode(&ctx, PM_KEYNAME); 408 th_cfg_set_parsemode(&ctx, PM_KEYNAME);
409 strPos = 0; 409 pos = 0;
410 } 410 }
411 else 411 else
412 { 412 {
413 // Error! Invalid character found 413 // Error! Invalid character found
414 ret = th_io_error(fh, THERR_INVALID_DATA, 414 ret = th_io_error(fh, THERR_INVALID_DATA,
442 ret = th_io_error(fh, THERR_INVALID_DATA, 442 ret = th_io_error(fh, THERR_INVALID_DATA,
443 "Config key name too long!"); 443 "Config key name too long!");
444 goto out; 444 goto out;
445 } 445 }
446 ctx.ch = -1; 446 ctx.ch = -1;
447 tmpStr[strPos] = 0; 447 str[pos] = 0;
448 } 448 }
449 else 449 else
450 { 450 {
451 // Error! Invalid character found 451 // Error! Invalid character found
452 tmpStr[strPos] = 0; 452 str[pos] = 0;
453 ret = th_io_error(fh, THERR_INVALID_DATA, 453 ret = th_io_error(fh, THERR_INVALID_DATA,
454 "Unexpected character '%c' in key name '%s'.", 454 "Unexpected character '%c' in key name '%s'.",
455 ctx.ch, tmpStr); 455 ctx.ch, str);
456 goto out; 456 goto out;
457 } 457 }
458 break; 458 break;
459 459
460 case PM_KEYSET: 460 case PM_KEYSET:
461 if (ctx.ch == '=') 461 if (ctx.ch == '=')
462 { 462 {
463 // Find key from configuration 463 // Find key from configuration
464 bool found; 464 bool found;
465 tmpStr[strPos] = 0; 465 str[pos] = 0;
466 466
467 for (item = sect, found = false; item != NULL && !found; ) 467 for (item = sect, found = false; item != NULL && !found; )
468 { 468 {
469 if (item->type != CFG_ITEM_COMMENT && 469 if (item->type != CFG_ITEM_COMMENT &&
470 item->name != NULL && 470 item->name != NULL &&
471 strcmp(item->name, tmpStr) == 0) 471 strcmp(item->name, str) == 0)
472 found = true; 472 found = true;
473 else 473 else
474 item = (th_cfgitem_t *) item->node.next; 474 item = (th_cfgitem_t *) item->node.next;
475 } 475 }
476 476
477 // Check if key was found 477 // Check if key was found
478 if (found) 478 if (found)
479 { 479 {
480 // Okay, set next mode 480 // Okay, set next mode
481 th_cfg_set_next_parsemode(&ctx, th_cfg_get_parsemode(item->type)); 481 th_cfg_set_next_parsemode(&ctx, th_cfg_get_parsemode(item->type));
482 isStart = true; 482 start = true;
483 fpSet = false; 483 fpseparator = false;
484 strPos = 0; 484 pos = 0;
485 } 485 }
486 else 486 else
487 { 487 {
488 // Error! No configuration key by this name found 488 // Error! No configuration key by this name found
489 ret = th_io_error(fh, THERR_INVALID_DATA, 489 ret = th_io_error(fh, THERR_INVALID_DATA,
490 "No such configuration setting: '%s'.", 490 "No such configuration setting: '%s'.",
491 tmpStr); 491 str);
492 goto out; 492 goto out;
493 } 493 }
494 494
495 ctx.ch = -1; 495 ctx.ch = -1;
496 } 496 }
518 ctx.ch = -1; 518 ctx.ch = -1;
519 } 519 }
520 else 520 else
521 { 521 {
522 // Next item found 522 // Next item found
523 th_cfg_set_parsemode(&ctx, ctx.nextMode); 523 th_cfg_set_parsemode(&ctx, ctx.next);
524 } 524 }
525 break; 525 break;
526 526
527 case PM_LIST: 527 case PM_LIST:
528 if (isStart) 528 if (start)
529 { 529 {
530 th_cfg_set_parsemode(&ctx, PM_STRING); 530 th_cfg_set_parsemode(&ctx, PM_STRING);
531 } 531 }
532 else 532 else
533 if (ctx.ch == ',') 533 if (ctx.ch == ',')
534 { 534 {
535 th_cfg_set_next_parsemode(&ctx, PM_STRING); 535 th_cfg_set_next_parsemode(&ctx, PM_STRING);
536 ctx.ch = -1; 536 ctx.ch = -1;
537 isStart = true; 537 start = true;
538 } 538 }
539 else 539 else
540 { 540 {
541 th_cfg_set_parsemode(&ctx, PM_IDLE); 541 th_cfg_set_parsemode(&ctx, PM_IDLE);
542 } 542 }
562 } 562 }
563 break; 563 break;
564 564
565 case PM_STRING: 565 case PM_STRING:
566 // String parsing mode 566 // String parsing mode
567 if (isStart) 567 if (start)
568 { 568 {
569 // Start of string, get delimiter 569 // Start of string, get delimiter
570 ctx.strDelim = ctx.ch; 570 ctx.delim = ctx.ch;
571 isStart = false; 571 start = false;
572 strPos = 0; 572 pos = 0;
573 isEscaped = false; 573 escaped = false;
574 } 574 }
575 else 575 else
576 if (!isEscaped && ctx.ch == ctx.strDelim) 576 if (!escaped && ctx.ch == ctx.delim)
577 { 577 {
578 // End of string, set the value 578 // End of string, set the value
579 tmpStr[strPos] = 0; 579 str[pos] = 0;
580 if ((ret = th_cfg_set_item(&ctx, item, tmpStr)) != THERR_OK) 580 if ((ret = th_cfg_set_item(&ctx, item, str)) != THERR_OK)
581 goto out; 581 goto out;
582 } 582 }
583 else 583 else
584 if (!isEscaped && ctx.ch == '\\') 584 if (!escaped && ctx.ch == '\\')
585 { 585 {
586 // Escape sequence 586 // Escape sequence
587 isEscaped = true; 587 escaped = true;
588 } 588 }
589 else 589 else
590 { 590 {
591 // Add character to string 591 // Add character to string
592 VADDCH(ctx.ch) 592 VADDCH(ctx.ch)
596 ret = th_io_error(fh, THERR_INVALID_DATA, 596 ret = th_io_error(fh, THERR_INVALID_DATA,
597 "String too long! Maximum is %d characters.", 597 "String too long! Maximum is %d characters.",
598 SET_CFG_MAX_PARSE_BUF); 598 SET_CFG_MAX_PARSE_BUF);
599 goto out; 599 goto out;
600 } 600 }
601 isEscaped = false; 601 escaped = false;
602 } 602 }
603 603
604 ctx.ch = -1; 604 ctx.ch = -1;
605 break; 605 break;
606 606
607 case PM_NUMERIC: 607 case PM_NUMERIC:
608 // Integer parsing mode 608 // Integer parsing mode
609 if (isStart && item->type == CFG_ITEM_UINT && ctx.ch == '-') 609 if (start && item->type == CFG_ITEM_UINT && ctx.ch == '-')
610 { 610 {
611 // Error! Negative values not allowed for unsigned ints 611 // Error! Negative values not allowed for unsigned ints
612 ret = th_io_error(fh, THERR_INVALID_DATA, 612 ret = th_io_error(fh, THERR_INVALID_DATA,
613 "Negative value specified for %s, unsigned value expected.", 613 "Negative value specified for %s, unsigned value expected.",
614 item->name); 614 item->name);
615 goto out; 615 goto out;
616 } 616 }
617 else 617 else
618 if (isStart && (ctx.ch == '-' || ctx.ch == '+')) 618 if (start && (ctx.ch == '-' || ctx.ch == '+'))
619 { 619 {
620 VADDCH(ctx.ch) 620 VADDCH(ctx.ch)
621 else 621 else
622 ret = THERR_INVALID_DATA; 622 ret = THERR_INVALID_DATA;
623 } 623 }
624 else 624 else
625 if (isStart && item->type == CFG_ITEM_FLOAT && ctx.ch == '.') 625 if (start && item->type == CFG_ITEM_FLOAT && ctx.ch == '.')
626 { 626 {
627 fpSet = true; 627 fpseparator = true;
628 VADDCH('0') 628 VADDCH('0')
629 else 629 else
630 ret = THERR_INVALID_DATA; 630 ret = THERR_INVALID_DATA;
631 631
632 VADDCH(ctx.ch) 632 VADDCH(ctx.ch)
633 else 633 else
634 ret = THERR_INVALID_DATA; 634 ret = THERR_INVALID_DATA;
635 } 635 }
636 else 636 else
637 if (item->type == CFG_ITEM_FLOAT && ctx.ch == '.' && !fpSet) 637 if (item->type == CFG_ITEM_FLOAT && ctx.ch == '.' && !fpseparator)
638 { 638 {
639 fpSet = true; 639 fpseparator = true;
640 VADDCH(ctx.ch) 640 VADDCH(ctx.ch)
641 else 641 else
642 ret = THERR_INVALID_DATA; 642 ret = THERR_INVALID_DATA;
643 } 643 }
644 else 644 else
650 } 650 }
651 else 651 else
652 if (th_cfg_is_end(ctx.ch)) 652 if (th_cfg_is_end(ctx.ch))
653 { 653 {
654 // End of integer parsing mode 654 // End of integer parsing mode
655 tmpStr[strPos] = 0; 655 str[pos] = 0;
656 656
657 if ((ret = th_cfg_set_item(&ctx, item, tmpStr)) != THERR_OK) 657 if ((ret = th_cfg_set_item(&ctx, item, str)) != THERR_OK)
658 goto out; 658 goto out;
659 659
660 th_cfg_set_parsemode(&ctx, PM_IDLE); 660 th_cfg_set_parsemode(&ctx, PM_IDLE);
661 } 661 }
662 else 662 else
675 "String too long! Maximum is %d characters.", 675 "String too long! Maximum is %d characters.",
676 SET_CFG_MAX_PARSE_BUF); 676 SET_CFG_MAX_PARSE_BUF);
677 goto out; 677 goto out;
678 } 678 }
679 679
680 isStart = false; 680 start = false;
681 ctx.ch = -1; 681 ctx.ch = -1;
682 break; 682 break;
683 683
684 case PM_BOOL: 684 case PM_BOOL:
685 // Boolean parsing mode 685 // Boolean parsing mode
686 if (isStart) 686 if (start)
687 { 687 {
688 isStart = false; 688 start = false;
689 strPos = 0; 689 pos = 0;
690 } 690 }
691 691
692 if (th_isalnum(ctx.ch)) 692 if (th_isalnum(ctx.ch))
693 { 693 {
694 VADDCH(ctx.ch) 694 VADDCH(ctx.ch)
696 ret = THERR_INVALID_DATA; 696 ret = THERR_INVALID_DATA;
697 } 697 }
698 else 698 else
699 if (th_cfg_is_end(ctx.ch)) 699 if (th_cfg_is_end(ctx.ch))
700 { 700 {
701 tmpStr[strPos] = 0; 701 str[pos] = 0;
702 ret = th_cfg_set_item(&ctx, item, tmpStr); 702 ret = th_cfg_set_item(&ctx, item, str);
703 } 703 }
704 704
705 if (ret != THERR_OK) 705 if (ret != THERR_OK)
706 { 706 {
707 ret = th_io_error(fh, ret, 707 ret = th_io_error(fh, ret,
713 break; 713 break;
714 } 714 }
715 } 715 }
716 716
717 out: 717 out:
718 th_free(tmpStr); 718 th_free(str);
719 719
720 // Return result 720 // Return result
721 if (ret == THERR_OK && ctx.parseMode == PM_ERROR) 721 if (ret == THERR_OK && ctx.mode == PM_ERROR)
722 ret = THERR_INVALID_DATA; 722 ret = THERR_INVALID_DATA;
723 723
724 return ret; 724 return ret;
725 } 725 }
726 726