Actual source code: yamlimpls.c

petsc-3.6.1 2015-08-06
Report Typos and Errors
  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(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(prefix);
 48:         }
 49:         (*lvl)++;
 50:         PetscParseLayerYAML(parser,lvl);
 51:         (*lvl)--;
 52:         if (*lvl > 0) {
 53:           PetscOptionsPrefixPop();
 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: }