Actual source code: yamlimpls.c
petsc-3.7.3 2016-08-01
1: #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
2: #if defined(PETSC_HAVE_STRING_H)
3: #include <string.h>
4: #endif
5: #include <yaml.h>
7: enum storage_flags {VAR,VAL,SEQ}; /* "Store as" switch */
11: PetscErrorCode PetscParseLayerYAML(yaml_parser_t *parser,int *lvl)
12: {
13: yaml_event_t event;
14: int storage = VAR; /* mapping cannot start with VAL definition w/o VAR key */
15: char key[PETSC_MAX_PATH_LEN],option[PETSC_MAX_PATH_LEN],prefix[PETSC_MAX_PATH_LEN];
16: PetscErrorCode ierr;
19: PetscSNPrintf(option,PETSC_MAX_PATH_LEN,"%s"," ");
20: do {
21: yaml_parser_parse(parser,&event);
22: /* Parse value either as a new leaf in the mapping */
23: /* or as a leaf value (one of them, in case it's a sequence) */
24: switch (event.type) {
25: case YAML_SCALAR_EVENT:
26: if (storage) {
27: PetscSNPrintf(option,PETSC_MAX_PATH_LEN,"-%s %s",key,(char*)event.data.scalar.value);
28: PetscOptionsInsertString(NULL,option);
29: } else {
30: PetscStrncpy(key,(char*)event.data.scalar.value,event.data.scalar.length+1);
31: }
32: storage ^= VAL; /* Flip VAR/VAL switch for the next event */
33: break;
34: case YAML_SEQUENCE_START_EVENT:
35: /* Sequence - all the following scalars will be appended to the last_leaf */
36: storage = SEQ;
37: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP ,"Unable to open YAML option file: sequences not supported");
38: yaml_event_delete(&event);
39: break;
40: case YAML_SEQUENCE_END_EVENT:
41: storage = VAR;
42: yaml_event_delete(&event);
43: break;
44: case YAML_MAPPING_START_EVENT:
45: PetscSNPrintf(prefix,PETSC_MAX_PATH_LEN,"%s_",key);
46: if (*lvl > 0) {
47: PetscOptionsPrefixPush(NULL,prefix);
48: }
49: (*lvl)++;
50: PetscParseLayerYAML(parser,lvl);
51: (*lvl)--;
52: if (*lvl > 0) {
53: PetscOptionsPrefixPop(NULL);
54: }
55: storage ^= VAL; /* Flip VAR/VAL, w/o touching SEQ */
56: yaml_event_delete(&event);
57: break;
58: default:
59: break;
60: }
61: }
62: while ((event.type != YAML_MAPPING_END_EVENT) && (event.type != YAML_STREAM_END_EVENT));
63: return(0);
64: }
68: /*C
70: PetscOptionsInsertFileYAML - Insert a YAML-formatted file in the option database
72: Collective on MPI_Comm
74: Input Parameter:
75: + comm - the processes that will share the options (usually PETSC_COMM_WORLD)
76: . file - name of file
77: - require - if PETSC_TRUE will generate an error if the file does not exist
80: Only a small subset of the YAML standard is implemented. Sequences and alias
81: are NOT supported.
82: The algorithm recursively parses the yaml file, pushing and popping prefixes
83: and inserting key + values pairs using PetscOptionsInsertString.
85: Inspired by http://stackoverflow.com/a/621451
87: Level: developer
89: .seealso: PetscOptionsSetValue(), PetscOptionsView(), PetscOptionsHasName(), PetscOptionsGetInt(),
90: PetscOptionsGetReal(), PetscOptionsGetString(), PetscOptionsGetIntArray(), PetscOptionsBool(),
91: PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
92: PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
93: PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
94: PetscOptionsFList(), PetscOptionsEList(), PetscOptionsInsertFile()
95: C*/
96: extern PetscErrorCode PetscOptionsInsertFileYAML(MPI_Comm comm,const char file[],PetscBool require)
97: {
99: PetscMPIInt rank;
100: char fname[PETSC_MAX_PATH_LEN];
101: unsigned char *optionsStr;
102: int yamlLength;
103: yaml_parser_t parser;
104: int lvl=0;
105: FILE *source;
106: PetscInt offset;
109: MPI_Comm_rank(comm,&rank);
110: if (!rank) {
111: PetscFixFilename(file,fname);
112: source = fopen(fname,"r");
113: if (source) {
114: fseek(source,0,SEEK_END);
115: yamlLength = ftell(source);
116: fseek(source,0,SEEK_SET);
117: PetscMalloc1(yamlLength+1,&optionsStr);
118: /* Read the content of the YAML file one char at a time*/
119: for (offset = 0; offset < yamlLength; offset++) {
120: fread(&(optionsStr[offset]), sizeof(unsigned char),1,source);
121: }
122: fclose(source);
123: optionsStr[yamlLength] = '\0';
124: } else if (require) {
125: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open YAML option file %s\n",fname);
126: }
127: MPI_Bcast(&yamlLength,1,MPI_INT,0,comm);
128: MPI_Bcast(optionsStr,yamlLength+1,MPI_UNSIGNED_CHAR,0,comm);
129: } else {
130: MPI_Bcast(&yamlLength,1,MPI_INT,0,comm);
131: PetscMalloc1(yamlLength+1,&optionsStr);
132: MPI_Bcast(optionsStr,yamlLength+1,MPI_UNSIGNED_CHAR,0,comm);
133: }
134: yaml_parser_initialize(&parser);
135: yaml_parser_set_input_string(&parser,optionsStr,(size_t) yamlLength);
136: PetscParseLayerYAML(&parser,&lvl);
137: yaml_parser_delete(&parser);
138: PetscFree(optionsStr);
139: return(0);
140: }