Date: 2013-07-02T14:39:31+00:00

Actual source code: yamlimpls.c
petsc-3.4.2 2013-07-02

      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:           PetscOptionsList(), 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:       PetscMalloc((yamlLength+1)*sizeof(unsigned char),&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:     PetscMalloc((yamlLength+1)*sizeof(unsigned char),&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: }