27 #ifndef FMS_MAX_FILE_LEN
28 #define FMS_MAX_FILE_LEN 255
31 #define FMS_FILE_LEN FMS_MAX_FILE_LEN
35 const int MISSING_FILE = -1;
36 const int PARSER_INIT_ERROR = -2;
37 const int INVALID_YAML = -3;
38 const int INVALID_ALIAS = -4;
39 const int MAX_LEVELS_REACH = -5;
40 const int SUCCESSFUL = 1;
47 #ifdef DEBUG_FMS_YAML_PARSER
48 #define DEBUG_PRINT(...) printf(__VA_ARGS__)
50 #define DEBUG_PRINT(...)
60 char key[FMS_FILE_LEN];
61 char value[FMS_FILE_LEN];
62 char parent_name[FMS_FILE_LEN];
72 char anchor_name[FMS_FILE_LEN];
75 char parent_names[MAX_LEVELS][FMS_FILE_LEN];
106 int get_nkeys_binding(
const int *file_id,
const int *block_id)
111 for (
int i = 1; i <= my_files.files[j].nkeys; i++)
113 if (my_files.files[j].keys[i].parent_key == *block_id &&
114 my_files.files[j].keys[i].parent_name[0] ==
'\0')
128 void get_key_ids_binding(
const int *file_id,
const int *block_id,
int *key_ids)
133 for (
int i = 1; i <= my_files.files[j].nkeys; i++)
135 if (my_files.files[j].keys[i].parent_key == *block_id &&
136 my_files.files[j].keys[i].parent_name[0] ==
'\0')
138 key_ids[key_count++] = i;
152 char *get_key(
const int *file_id,
const int *key_id)
154 return my_files.files[*file_id].keys[*key_id].key;
166 char *get_value(
const int *file_id,
const int *key_id)
168 return my_files.files[*file_id].keys[*key_id].value;
180 char *get_block(
const int *file_id,
const int *block_id)
182 return my_files.files[*file_id].keys[*block_id].parent_name;
196 char *get_value_from_key_wrap(
const int *file_id,
const int *block_id,
const char *key_name,
int *success)
203 for (i = 1; i <= my_files.files[j].nkeys; i++)
205 if (my_files.files[j].keys[i].parent_key == *block_id)
207 if (strcmp(my_files.files[j].keys[i].key, key_name) == 0)
210 return my_files.files[j].keys[i].value;
228 int get_num_blocks_all(
const int *file_id,
const char *block_name)
235 for (i = 1; i <= my_files.files[fid].nkeys; i++)
237 if (strcmp(my_files.files[fid].keys[i].parent_name, block_name) == 0)
253 int get_num_unique_blocks_bind(
const int *file_id,
const int *parent_block_id)
258 char block_names[my_files.files[fid].nkeys][FMS_FILE_LEN];
261 for (i = 1; i <= my_files.files[fid].nkeys; i++)
263 if (my_files.files[fid].keys[i].parent_key == *parent_block_id)
265 if (strcmp(my_files.files[fid].keys[i].parent_name,
"") == 0)
269 for (k = 0; k < nblocks; k++)
271 if (strcmp(block_names[k], my_files.files[fid].keys[i].parent_name) == 0)
281 strcpy(block_names[nblocks], my_files.files[fid].keys[i].parent_name);
296 void get_unique_block_ids_bind(
const int *file_id,
int *block_ids,
const int *parent_block_id)
301 char block_names[my_files.files[fid].nkeys][FMS_FILE_LEN];
304 for (i = 1; i <= my_files.files[fid].nkeys; i++)
306 if (my_files.files[fid].keys[i].parent_key == *parent_block_id)
308 if (strcmp(my_files.files[fid].keys[i].parent_name,
"") == 0)
312 for (k = 0; k < nblocks; k++)
314 if (strcmp(block_names[k], my_files.files[fid].keys[i].parent_name) == 0)
324 block_ids[nblocks] = my_files.files[fid].keys[i].key_id;
325 strcpy(block_names[nblocks], my_files.files[fid].keys[i].parent_name);
339 int get_num_blocks_child(
const int *file_id,
const char *block_name,
const int *parent_block_id)
345 for (i = 1; i <= my_files.files[fid].nkeys; i++)
347 if (strcmp(my_files.files[fid].keys[i].parent_name, block_name) == 0 &&
348 my_files.files[fid].keys[i].parent_key == *parent_block_id)
366 void get_block_ids_all(
const int *file_id,
const char *block_name,
int *block_ids)
373 for (i = 1; i <= my_files.files[fid].nkeys; i++)
375 if (strcmp(my_files.files[fid].keys[i].parent_name, block_name) == 0)
377 block_ids[nblocks] = my_files.files[fid].keys[i].key_id;
394 void get_block_ids_child(
const int *file_id,
const char *block_name,
int *block_ids,
const int *parent_key_id)
400 for (
int i = 1; i <= my_files.files[fid].nkeys; i++ )
402 if(strcmp(my_files.files[fid].keys[i].parent_name, block_name) == 0 &&
403 my_files.files[fid].keys[i].parent_key == *parent_key_id)
405 block_ids[nblocks++] = my_files.files[fid].keys[i].key_id;
421 bool is_valid_block_id(
const int *file_id,
const int *block_id)
426 if (bid <= -1 || bid > my_files.files[fid].nkeys) {
430 if (bid != 0 && strcmp(my_files.files[fid].keys[bid].parent_name,
"") == 0) {
446 bool is_valid_key_id(
const int *file_id,
const int *key_id)
451 return (kid > -1 && kid <= my_files.files[fid].nkeys);
462 bool is_valid_file_id(
const int *file_id)
466 return (fid > -1 && fid < nfiles);
480 int increment_nlevels(
int *nlevels) {
482 if (*nlevels > MAX_LEVELS){
483 return MAX_LEVELS_REACH;
494 void init_anchor(AnchorsType *anchor,
const char *name,
const char *parent_name)
496 if (anchor == NULL || name == NULL)
return;
499 anchor->keys = (KeyValuePairs*)calloc(1,
sizeof(KeyValuePairs));
500 strcpy(anchor->anchor_name, name);
503 strcpy(anchor->parent_names[0], parent_name);
516 void add_key(KeyValuePairs *my_key,
const int key_id,
const int parent_key,
517 const char *key,
const char *value,
const char *parent_name) {
519 my_key->key_id = key_id;
520 my_key->parent_key = parent_key;
523 strncpy(my_key->key, key,
sizeof(my_key->key) - 1);
524 my_key->key[
sizeof(my_key->key) - 1] =
'\0';
526 my_key->key[0] =
'\0';
530 strncpy(my_key->value, value,
sizeof(my_key->value) - 1);
531 my_key->value[
sizeof(my_key->value) - 1] =
'\0';
533 my_key->value[0] =
'\0';
537 strncpy(my_key->parent_name, parent_name,
sizeof(my_key->parent_name) - 1);
538 my_key->parent_name[
sizeof(my_key->parent_name) - 1] =
'\0';
540 my_key->parent_name[0] =
'\0';
551 void add_anchor_key(AnchorsType *anchor,
const char *key,
const char *value)
554 anchor->keys = realloc(anchor->keys, (anchor->nkeys+1)*
sizeof(KeyValuePairs));
556 KeyValuePairs *my_key = &anchor->keys[anchor->nkeys];
557 add_key(my_key, anchor->nkeys, anchor->pid[anchor->nlevels],
560 DEBUG_PRINT(
"ANCHOR :: Key_number: %i, parent_key: %i, %s:%s \n ", my_key->key_id, my_key->parent_key, my_key->key, my_key->value);
570 int add_anchor_parent(AnchorsType *anchor,
const char *key)
574 anchor->keys = realloc(anchor->keys, (anchor->nkeys+1)*
sizeof(KeyValuePairs));
575 int err_code = increment_nlevels(&anchor->nlevels);
576 if (err_code =! SUCCESSFUL)
return err_code;
578 anchor->pid[anchor->nlevels] = anchor->nkeys;
580 if (strcmp(key,
"")) {
581 strcpy(anchor->parent_names[anchor->nlevels],key );
583 KeyValuePairs *my_key = &anchor->keys[anchor->nkeys];
584 add_key(my_key, anchor->nkeys, anchor->pid[anchor->nlevels -1],
585 "",
"", anchor->parent_names[anchor->nlevels]);
586 DEBUG_PRINT(
"ANCHOR :: Key_number: %i, parent_key: %i, parent_name: %s \n ", my_key->key_id, my_key->parent_key, my_key->parent_name);
601 int get_anchor_id(YamlFile *
this,
const char *alias_name)
603 for (
int i = 1; i < this->nanchors + 1; i++) {
604 AnchorsType *my_anchor = &this->Anchors[i];
605 if (strcmp(my_anchor->anchor_name, alias_name) == 0) {
609 return INVALID_ALIAS;
619 int open_and_parse_file_wrap(
const char *filename,
int *file_id)
621 yaml_parser_t parser;
629 my_files.files = (YamlFile*)calloc(1,
sizeof(YamlFile));
632 my_files.files = realloc(my_files.files, (nfiles+1)*
sizeof(YamlFile));
639 DEBUG_PRINT(
"Opening file: %s.\n There are %i files opened.\n", filename, nfiles);
642 file = fopen(filename,
"r");
643 if (file == NULL)
return MISSING_FILE;
645 if(!yaml_parser_initialize(&parser))
return PARSER_INIT_ERROR;
647 YamlFile *my_file = &my_files.files[fid];
648 my_file->keys = (KeyValuePairs*)calloc(1,
sizeof(KeyValuePairs));
653 char parent_names[MAX_LEVELS][FMS_FILE_LEN];
654 char key_value[FMS_FILE_LEN];
656 bool defining_anchor;
659 defining_value =
false;
660 defining_anchor =
false;
662 strcpy(parent_names[0],
"TOP");
664 yaml_parser_set_input_file(&parser, file);
666 if (!yaml_parser_scan(&parser, &token)) {
672 DEBUG_PRINT(
"YAML_KEY_TOKEN \n");
673 defining_value =
false;
676 case YAML_VALUE_TOKEN:
677 DEBUG_PRINT(
"YAML_VALUE_TOKEN \n");
678 defining_value =
true;
681 case YAML_SCALAR_TOKEN:
682 DEBUG_PRINT(
"YAML_SCALAR_TOKEN \n");
683 if (!defining_value) {
684 strcpy(key_value, token.data.scalar.value);
687 if (defining_anchor) {
688 AnchorsType *my_anchor = &my_file->Anchors[my_file->nanchors];
689 add_anchor_key(my_anchor, key_value, token.data.scalar.value);
692 my_file->keys = realloc(my_file->keys, (nkeys+1)*
sizeof(KeyValuePairs));
693 KeyValuePairs *my_key = &my_file->keys[nkeys];
694 add_key(my_key, nkeys, pid[nlevels],
695 key_value, token.data.scalar.value,
"");
696 DEBUG_PRINT(
"Key_number: %i, parent_key: %i, ----- %s:%s \n ",
697 my_file->keys[nkeys].key_id, my_file->keys[nkeys].parent_key,
698 my_file->keys[nkeys].key, my_file->keys[nkeys].value);
700 defining_value =
false;
701 strcpy(key_value,
"" );
704 case YAML_BLOCK_ENTRY_TOKEN:
705 DEBUG_PRINT(
"YAML_BLOCK_ENTRY_TOKEN \n");
706 if (defining_anchor) {
707 AnchorsType *my_anchor = &my_file->Anchors[my_file->nanchors];
709 int err_code = add_anchor_parent(my_anchor, key_value);
710 if (err_code != SUCCESSFUL)
return err_code;
713 int err_code = increment_nlevels(&nlevels);
714 if (err_code == MAX_LEVELS_REACH)
return MAX_LEVELS_REACH;
717 pid[nlevels] = nkeys;
718 if (strcmp(key_value,
"")) {
719 strcpy(parent_names[nlevels], key_value);
721 my_file->keys = realloc(my_file->keys, (nkeys+1)*
sizeof(KeyValuePairs));
722 KeyValuePairs *my_key = &my_file->keys[nkeys];
723 add_key(my_key, nkeys, pid[nlevels-1],
724 "",
"", parent_names[nlevels]);
725 DEBUG_PRINT(
"Key_number: %i, parent_key: %i, parent_name: %s \n ", my_file->keys[nkeys].key_id, my_file->keys[nkeys].parent_key, my_file->keys[nkeys].parent_name);
727 defining_value =
false;
728 strcpy(key_value,
"" );
730 case YAML_BLOCK_END_TOKEN:
731 DEBUG_PRINT(
"YAML_BLOCK_END_TOKEN \n");
732 if (defining_anchor) {
733 AnchorsType *my_anchor = &my_file->Anchors[my_file->nanchors];
734 my_anchor->nlevels--;
735 if (my_anchor->nlevels == -1) {
736 defining_anchor =
false;
737 DEBUG_PRINT(
"FINISHED WITH ANCHOR :: ----------------------------- \n");
742 defining_value =
false;
743 strcpy(key_value,
"" );
745 case YAML_ANCHOR_TOKEN: {
746 DEBUG_PRINT(
"YAML_ANCHOR_TOKEN \n");
747 my_file->nanchors ++;
748 if (my_file->nanchors == 1) {
749 my_file->Anchors = (AnchorsType*)calloc(my_file->nanchors + 1,
sizeof(AnchorsType));
751 my_file->Anchors = realloc(my_file->Anchors, (my_file->nanchors + 1)*
sizeof(AnchorsType));
753 defining_anchor =
true;
754 defining_value =
false;
755 AnchorsType *my_anchor = &my_file->Anchors[my_file->nanchors];
756 init_anchor(my_anchor, token.data.anchor.value, key_value);
759 case YAML_ALIAS_TOKEN: {
760 DEBUG_PRINT(
"YAML_ALIAS_TOKEN \n");
763 int aid = get_anchor_id(my_file, token.data.alias.value);
764 if (aid == INVALID_ALIAS)
return INVALID_ALIAS;
766 AnchorsType *my_anchor = &my_file->Anchors[aid];
767 for (
int i = 2; i < my_anchor->nkeys + 1; i++) {
769 my_file->keys = realloc(my_file->keys, (nkeys+1)*
sizeof(KeyValuePairs));
770 KeyValuePairs *my_key = &my_file->keys[nkeys];
772 char parent_name[FMS_FILE_LEN];
773 if (my_anchor->keys[i].parent_key == 0){
774 strcpy(parent_name, parent_names[nlevels]);
775 parent_key_id = pid[nlevels-1];
777 strcpy(parent_name, my_anchor->keys[i].parent_name);
778 parent_key_id = top_key + my_anchor->keys[i].parent_key - 1;
780 add_key(my_key, nkeys, parent_key_id,
781 my_anchor->keys[i].key, my_anchor->keys[i].value, parent_name);
782 if (strcmp(my_file->keys[nkeys].key,
"")) {
783 DEBUG_PRINT(
"**:: Key_number: %i, parent_key: %i, ----- %s:%s \n ",
784 my_file->keys[nkeys].key_id, my_file->keys[nkeys].parent_key,
785 my_file->keys[nkeys].key, my_file->keys[nkeys].value);
787 DEBUG_PRINT(
"**:: Key_number: %i, parent_key: %i, parent_name: %s \n ",
788 my_file->keys[nkeys].key_id, my_file->keys[nkeys].parent_key,
789 my_file->keys[nkeys].parent_name);
797 if(token.type != YAML_STREAM_END_TOKEN)
798 yaml_token_delete(&token);
799 }
while(token.type != YAML_STREAM_END_TOKEN);
800 yaml_token_delete(&token);
801 yaml_parser_delete(&parser);
803 my_file->nkeys = nkeys;
805 DEBUG_PRINT(
"closing file: %s\n", filename);