IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 12, 2005, 9:12:01 AM (21 years ago)
Author:
desonia
Message:

massive restructuring of codebase.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/xml/psXML.c

    r4432 r4540  
    1 /** @file  psMetadataIO.c
     1/** @file  psXML.c
    22*
    3 *  @brief Contains metadata input/output functions.
     3*  @brief Contains XML input/output functions.
    44*
    5 *  This file defines functions to read and write metadata to/from an external file.
     5*  This file defines functions to read metadata from an XML file.
    66*
    7 *  @ingroup Metadata
     7*  @ingroup XML
    88*
    99*  @author Ross Harman, MHPCC
    1010*  @author Eric Van Alst, MHPCC
    1111*
    12 *  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
    13 *  @date $Date: 2005-06-30 00:04:12 $
     12*  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2005-07-12 19:12:01 $
    1414*
    1515*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    1717
    1818#include <libxml/parser.h>
    19 #include <fitsio.h>
    2019#include <string.h>
    2120#include <ctype.h>
    2221#include <limits.h>
    2322
    24 #include "psAbort.h"
    25 #include "psType.h"
     23#include "psXML.h"
    2624#include "psMemory.h"
    2725#include "psError.h"
    2826#include "psString.h"
    29 #include "psList.h"
    30 #include "psHash.h"
    31 #include "psVector.h"
    32 #include "psMetadata.h"
    33 #include "psMetadataIO.h"
    3427#include "psConstants.h"
    35 #include "psAstronomyErrors.h"
     28#include "psErrorText.h"
    3629
    3730/******************************************************************************/
     
    3932/******************************************************************************/
    4033
    41 /** Check for FITS errors */
    42 #define FITS_ERROR(STRING,PS_ERROR)                                                                          \
    43 fits_get_errstatus(status, fitsErr);                                                                         \
    44 psError(PS_ERR_IO,true, STRING, PS_ERROR, fitsErr);                                                          \
    45 status = 0;                                                                                                  \
    46 fits_close_file(fd, &status);                                                                                \
    47 if(status){                                                                                                  \
    48     fits_get_errstatus(status, fitsErr);                                                                     \
    49     psError(PS_ERR_IO,true, "Couldn't close FITS file. FITS error: %s", fitsErr);                            \
    50 }                                                                                                            \
    51 status = 0;                                                                                                  \
    52 psFree(output);                                                                                              \
    53 return NULL;
    54 
    5534/** Maximum size of a FITS line */
    5635#define FITS_LINE_SIZE 80
     
    5938#define MAX_STRING_LENGTH 256
    6039
    61 
    62 /******************************************************************************/
    63 /*  TYPE DEFINITIONS                                                          */
    64 /******************************************************************************/
    65 
    66 // None
    67 
    68 /*****************************************************************************/
    69 /*  GLOBAL VARIABLES                                                         */
    70 /*****************************************************************************/
    71 
    72 // None
    73 
    74 /*****************************************************************************/
    75 /*  FILE STATIC VARIABLES                                                    */
    76 /*****************************************************************************/
    77 
    78 // None
    79 
    80 /*****************************************************************************/
    81 /*  FUNCTION IMPLEMENTATION - LOCAL                                          */
    82 /*****************************************************************************/
    83 
    84 static void saxEndElement(void *ctx, const xmlChar *tagName);
    85 static void initVectorXml(void *ctx, char *tagName);
    86 static void initMetadataItemXml(void *ctx, char *tagName);
    87 static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
    88 static psMetadata* getMetadataType(char *linePtr);
    89 static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
    90 ;
    91 static void parseLevelInfoFree(p_psParseLevelInfo* info);
    92 static psBool parseLine(psS32* level,   psArray* levelArray,
    93                         char*  linePtr, psS32 lineCount,     char* fileName, psBool overwrite);
    94 static psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
    95                                 char* linePtr, psS32  lineCount, char*    fileName,    psMetadataFlags flags);
    96 
    97 static void parseLevelInfoFree(p_psParseLevelInfo* info)
    98 {
    99     psFree(info->nonUniqueKeyArray);
    100     psFree(info->typeArray);
    101     psFree(info->templateArray);
    102     psFree(info->name);
    103     psFree(info->metadata);
    104 }
    105 
    106 // Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
    107 // must be null terminated.
    108 psBool ignoreLine(char *inString)
    109 {
    110     while(*inString!='\0' && *inString!='#') {
    111         if(!isspace(*inString)) {
    112             return false;
    113         }
    114         inString++;
    115     }
    116 
    117     return true;
    118 }
    119 
    120 
    121 //  Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
    122 //  terminated copy of the original input string.
    123 char *cleanString(char *inString, psS32 sLen, psBool ignoreComment)
    124 {
    125     char *ptrB = NULL;
    126     char *ptrE = NULL;
    127     char *cleaned = NULL;
    128 
    129     // Initialize begining of string pointer
    130     ptrB = inString;
    131 
    132     // Skip over leading # or whitespace
    133     if(ignoreComment) {
    134         while (isspace(*ptrB) || *ptrB=='#') {
    135             ptrB++;
    136         }
    137     } else {
    138         while (isspace(*ptrB)) {
    139             ptrB++;
    140         }
    141     }
    142 
    143     // Skip over trailing whitespace, null terminators, and # characters
    144     ptrE = inString + sLen;
    145     if(ignoreComment) {
    146         while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
    147             ptrE--;
    148         }
    149     } else {
    150         while(isspace(*ptrE) || *ptrE=='\0') {
    151             ptrE--;
    152         }
    153     }
    154 
    155     // Length, sLen, does not include '\0'
    156     sLen = ptrE - ptrB + 1;
    157 
    158     // Adds '\0' to end of string and +1 to sLen
    159     if(sLen < 0 ) {
    160         cleaned = NULL;
    161     } else {
    162         cleaned = psStringNCopy(ptrB, sLen);
    163     }
    164 
    165     return cleaned;
    166 }
    167 
    168 // Count repeat occurances of a single character within a line. The input string must be null terminated.
    169 psS32 repeatedChars(char *inString, char ch)
    170 {
    171     psS32 count = 0;
    172 
    173     while(*inString!='\0') {
    174         if(*inString == ch) {
    175             count++;
    176         }
    177         inString++;
    178     }
    179 
    180     return count;
    181 }
    182 
    183 // Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
    184 // the beginning of the string. Tokens are newly allocated null terminated strings.
    185 char* getToken(char **inString, char *delimiter, psS32 *status, psBool ignoreComment)
    186 {
    187     char *cleanToken = NULL;
    188     char *convertChar = NULL;
    189     psS32 sLen = 0;
    190 
    191     // Convert tab characters to white space
    192     while((convertChar=strchr(*inString,'\t')) != NULL ) {
    193         *convertChar = ' ';
    194     }
    195 
    196     // Skip over leading whitespace
    197     while(isspace(**inString)) {
    198         (*inString)++;
    199     }
    200 
    201     // Length of token, not including delimiter
    202     sLen = strcspn(*inString, delimiter);
    203     if(sLen) {
    204 
    205         // Create new, cleaned, and null terminated token
    206         cleanToken = cleanString(*inString, sLen,ignoreComment);
    207 
    208         // Move to end of token
    209         (*inString) += sLen;
    210     } else if(**inString!='\0' && sLen==0) {
    211         *status = 1;
    212     }
    213 
    214     return cleanToken;
    215 }
    216 
    21740// Returns single parsed value as a double precision number. The input string must be cleaned and null
    21841// terminated.
    219 double parseValue(char *inString, psS32 *status)
     42static double parseValue(char *inString, psS32 *status)
    22043{
    22144    char *end = NULL;
     
    23356
    23457/** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */
    235 psBool parseBool(char *inString, psS32 *status)
     58static psBool parseBool(char *inString, psS32 *status)
    23659{
    23760    psBool value = false;
     
    25073
    25174/** Returns parsed vector filled with with data. The input string must be null terminated. */
    252 psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
     75static psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
    25376{
    25477    char*      end       = NULL;
     
    332155
    333156    return vec;
    334 }
    335 
    336 /*****************************************************************************/
    337 /* FUNCTION IMPLEMENTATION - PUBLIC                                          */
    338 /*****************************************************************************/
    339 
    340 p_psParseLevelInfo* p_psParseLevelInfoAlloc(void)
    341 {
    342 
    343     p_psParseLevelInfo* info = NULL;
    344 
    345     // Allocate memory for parse level info
    346     info = (p_psParseLevelInfo*)psAlloc(sizeof(p_psParseLevelInfo));
    347 
    348     // If allocation successful then initialize members
    349     if(info != NULL) {
    350 
    351         info->nonUniqueKeyArray = psArrayAlloc(10);
    352         info->nonUniqueKeyArray->n = 0;
    353 
    354         info->typeArray = psArrayAlloc(10);
    355         info->typeArray->n = 0;
    356 
    357         info->templateArray = psArrayAlloc(10);
    358         info->templateArray->n = 0;
    359 
    360         info->metadata = NULL;
    361         info->name = NULL;
    362 
    363         // Set memory deallocator
    364         psMemSetDeallocator(info,(psFreeFunc)parseLevelInfoFree);
    365     }
    366     return info;
    367 }
    368 
    369 bool psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* item)
    370 {
    371     psMetadataType type;
    372     psBool success = true;
    373 
    374     PS_ASSERT_PTR_NON_NULL(fd, success);
    375     PS_ASSERT_PTR_NON_NULL(format, success);
    376     PS_ASSERT_PTR_NON_NULL(item, success);
    377 
    378     type = item->type;
    379 
    380     // determining the format type
    381     char* fType = strchr(format,'%');
    382     if (fType == NULL) {
    383         // well, the format contains no reference to the metadataItem's data:
    384         // that is truly trival to do!
    385         fprintf(fd,format);
    386         return success;
    387     }
    388 
    389     // skip over any format modifiers
    390     const char* formatEnd = format+strlen(format);
    391     while ( (fType < formatEnd) &&
    392         (strchr(" +-01234567890.$#, hlL",*(++fType)) != NULL) ) {}
    393 
    394     #define METADATAITEM_NUMERIC_CAST(FORMAT_TYPE) { \
    395         switch(type) { \
    396         case PS_META_BOOL: \
    397             fprintf(fd, format, (FORMAT_TYPE) item->data.B); \
    398             break; \
    399         case PS_META_S32: \
    400             fprintf(fd,format,(FORMAT_TYPE)  item->data.S32); \
    401             break; \
    402         case PS_META_F32: \
    403             fprintf(fd, format,(FORMAT_TYPE)  item->data.F32); \
    404             break; \
    405         case PS_META_F64: \
    406             fprintf(fd, format,(FORMAT_TYPE) item->data.F64); \
    407             break; \
    408         default: \
    409             psError(PS_ERR_BAD_PARAMETER_TYPE,true, \
    410                     PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type); \
    411             success = false; \
    412         } \
    413     }
    414 
    415     switch(*fType) {
    416     case 'd':
    417     case 'i':
    418     case 'c':
    419         METADATAITEM_NUMERIC_CAST(int)
    420         break;
    421     case 'o':
    422     case 'u':
    423     case 'x':
    424     case 'X':
    425         METADATAITEM_NUMERIC_CAST(unsigned int)
    426         break;
    427     case 'e':
    428     case 'E':
    429     case 'f':
    430     case 'F':
    431     case 'g':
    432     case 'G':
    433     case 'a':
    434     case 'A':
    435         METADATAITEM_NUMERIC_CAST(double)
    436         break;
    437     case 's':
    438         if (type == PS_META_STR) {
    439             fprintf(fd,format,(char*)item->data.V);
    440         } else {
    441             psError(PS_ERR_BAD_PARAMETER_TYPE,true,
    442                     PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
    443             success = false;
    444         }
    445         break;
    446     case 'p':
    447         fprintf(fd,format,item->data.V);
    448         break;
    449     default:
    450         psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    451                 PS_ERRORTEXT_psMetadata_FORMAT_INVALID, *fType);
    452         break;
    453     }
    454 
    455     return success;
    456 }
    457 
    458 
    459 psMetadata* psMetadataReadHeader(psMetadata* output, char *extName, psS32 extNum, char *fileName)
    460 {
    461     psBool tempBool;
    462     psBool success;
    463     char keyType;
    464     char keyName[FITS_LINE_SIZE];
    465     char keyValue[FITS_LINE_SIZE];
    466     char keyComment[FITS_LINE_SIZE];
    467     char fitsErr[MAX_STRING_LENGTH];
    468     psS32 i;
    469     psS32 hduType = 0;
    470     psS32 status = 0;
    471     psS32 numKeys = 0;
    472     psS32 keyNum = 0;
    473     fitsfile *fd = NULL;
    474 
    475     PS_ASSERT_PTR_NON_NULL(fileName,NULL);
    476 
    477     fits_open_file(&fd, fileName, READONLY, &status);
    478     if(fd == NULL || status != 0) {
    479         FITS_ERROR("FITS error while opening file: %s %s", fileName);
    480         return NULL;
    481     }
    482 
    483     if (extName == NULL && extNum < 1) {
    484         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    485                 PS_ERRORTEXT_psMetadataIO_EXTNUM_NOTPOSITIVE,
    486                 extNum);
    487         return NULL;
    488     }
    489 
    490     // Allocate metadata if user didn't
    491     if (output == NULL) {
    492         output = psMetadataAlloc();
    493     }
    494 
    495     // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
    496     if (extName != NULL) {
    497         if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {
    498             FITS_ERROR("FITS error while locating header %s: %s", extName);
    499         }
    500     } else {
    501         if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {
    502             FITS_ERROR("FITS error while locating header %d: %s", extNum);
    503         }
    504     }
    505 
    506     // Get number of key names
    507     if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
    508         FITS_ERROR("FITS error while reading key %d: %s", keyNum);
    509     }
    510 
    511     // Get each key name. Keywords start at one.
    512     for (i = 1; i <= numKeys; i++) {
    513         if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
    514             FITS_ERROR("FITS error while reading key %d: %s", keyNum);
    515         }
    516         if (fits_get_keytype(keyValue, &keyType, &status) != 0) {
    517             fits_get_errstatus(status, fitsErr);
    518             if (status != VALUE_UNDEFINED) {
    519                 FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
    520             } else {
    521                 // Some keywords are still valid if they don't have a type (like COMMENTS and HISTORY)
    522                 keyType = 'C';
    523                 status = 0;
    524             }
    525         }
    526 
    527         switch (keyType) {
    528         case 'I':
    529             success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
    530                                     PS_META_S32 | PS_META_DUPLICATE_OK,
    531                                     keyComment, atoi(keyValue));
    532             break;
    533         case 'F':
    534             success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
    535                                     PS_META_F64 | PS_META_DUPLICATE_OK,
    536                                     keyComment, atof(keyValue));
    537             break;
    538         case 'C':
    539             success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
    540                                     PS_META_STR | PS_META_DUPLICATE_OK,
    541                                     keyComment, keyValue);
    542             break;
    543         case 'L':
    544             tempBool = (keyValue[0] == 'T') ? 1 : 0;
    545             success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
    546                                     PS_META_BOOL | PS_META_DUPLICATE_OK,
    547                                     keyComment, tempBool);
    548             break;
    549         case 'U':
    550         case 'X':
    551         default:
    552             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FITS_METATYPE_INVALID, keyType);
    553             return output;
    554         }
    555 
    556         if (!success) {
    557             psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadataIO_ADD_FAILED, keyName);
    558             return output;
    559         }
    560     }
    561 
    562     return output;
    563 }
    564 
    565 static psMetadata* getMetadataType(char* linePtr)
    566 {
    567     psMetadata*     metadataTemplate = NULL;
    568     psS32           status           = 0;
    569     char*           token            = NULL;
    570     psMetadataItem* tempItem         = NULL;
    571 
    572     // Loop through line and generate metadata items for each token found
    573     while((token = getToken(&linePtr," ",&status,false)) != NULL ) {
    574 
    575         // If not allocated then allocate new metadata
    576         if(metadataTemplate == NULL) {
    577             metadataTemplate = psMetadataAlloc();
    578         }
    579 
    580         // Look for comment indicator #
    581         if(strstr(token,"#") != 0) {
    582             psFree(token);
    583             break;
    584         }
    585 
    586         // Create metadata item to represent token read
    587         tempItem = psMetadataItemAllocStr(token,"","");
    588         if(tempItem == NULL) {
    589             psFree(metadataTemplate);
    590             psFree(token);
    591             metadataTemplate = NULL;
    592             break;
    593         }
    594 
    595         // Add item to template
    596         if(!psMetadataAddItem(metadataTemplate, tempItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
    597             psFree(metadataTemplate);
    598             psFree(tempItem);
    599             psFree(token);
    600             metadataTemplate = NULL;
    601             break;
    602         }
    603         psFree(tempItem);
    604         psFree(token);
    605     }
    606 
    607     return metadataTemplate;
    608 }
    609 
    610 static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
    611 {
    612     psMetadata*      md           = NULL;
    613     psS32            items        = 0;
    614     char*            token        = NULL;
    615     psS32            status       = 0;
    616     psMetadataItem*  mdItem       = NULL;
    617     psMetadataItem*  templateItem = NULL;
    618     psListIterator*  iter         = NULL;
    619 
    620     // Determine the number of items in template
    621     items = template->list->size;
    622     if(items > 0 ) {
    623 
    624         // Allocate metadata
    625         md = psMetadataAlloc()
    626              ;
    627 
    628         // Point to first item in template
    629         iter = psListIteratorAlloc(template->
    630                                    list,PS_LIST_HEAD,true);
    631 
    632         // For each item in template parse line string for values
    633         for(psS32 i = 0;
    634                 i < items;
    635                 i++) {
    636 
    637             // Get template item
    638             templateItem = psListGetAndIncrement(iter)
    639                            ;
    640             if(templateItem == NULL) {
    641                 psFree(md);
    642                 md = NULL;
    643                 break;
    644             }
    645 
    646             // Get the next token on the line
    647             token = getToken(&linePtr," ",&status,false);
    648             if(token != NULL) {
    649                 // Allocate metadata item
    650                 mdItem = psMetadataItemAllocStr(templateItem->name,templateItem->comment,token);
    651                 if(mdItem == NULL) {
    652                     psFree(md);
    653                     md = NULL;
    654                     psFree(token);
    655                     break;
    656                 }
    657                 // Add item to metadata
    658                 if(!psMetadataAddItem(md, mdItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
    659                     psFree(md);
    660                     md = NULL;
    661                     psFree(mdItem);
    662                     psFree(token);
    663                     break;
    664                 }
    665                 psFree(mdItem);
    666             } else {
    667                 // Missing items
    668                 psFree(md);
    669                 md = NULL;
    670                 break;
    671             }
    672 
    673             psFree(token);
    674         }
    675         psFree(iter);
    676     }
    677     return md;
    678 }
    679 
    680 psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
    681                          char* linePtr, psS32  lineCount, char*    fileName,   psMetadataFlags flags)
    682 {
    683     psBool               returnValue   = true;
    684     psBool               addStatus     = false;
    685     psMetadataType       mdType        = PS_META_UNKNOWN;
    686     psElemType           vectorType    = PS_TYPE_S8;
    687     char*                strType       = NULL;
    688     char*                strValue      = NULL;
    689     char*                strComment    = NULL;
    690     psS32                status        = 0;
    691     psMetadata*          md            = NULL;
    692     psF64                tempDbl       = 0.0;
    693     psBool               tempBool      = false;
    694     psS32                tempInt       = 0;
    695     psVector*            tempVec       = NULL;
    696     char*                tempStr       = NULL;
    697     psArray*             nonUniqueKeys = NULL;
    698     psBool               typeFound     = false;
    699     psArray*             typeArray     = NULL;
    700     psArray*             templateArray = NULL;
    701     psMetadata*          tempMeta      = NULL;
    702     p_psParseLevelInfo*  nextLevelInfo = NULL;
    703 
    704     // Get the metadata item type
    705     strType = getToken(&linePtr, " ", &status,true);
    706 
    707     // Check for no type
    708     if(strType==NULL) {
    709         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,
    710                 fileName);
    711         returnValue = false;
    712     } else {
    713 
    714         // Set metadata type based on type token
    715 
    716         // Check if the keyName specifies a vector and if so use strType token to find vector type
    717         if(*keyName == '@') {
    718             mdType = PS_META_VEC;
    719             // Get the type of vector
    720             if(!strncmp(strType, "U8", 2)) {
    721                 vectorType = PS_TYPE_U8;
    722             } else if (!strncmp(strType,"U16",3)) {
    723                 vectorType = PS_TYPE_U16;
    724             } else if (!strncmp(strType,"U32",3)) {
    725                 vectorType = PS_TYPE_U32;
    726             } else if (!strncmp(strType,"U64",3)) {
    727                 vectorType = PS_TYPE_U64;
    728             } else if (!strncmp(strType,"S8",2)) {
    729                 vectorType = PS_TYPE_S8;
    730             } else if (!strncmp(strType,"S16",3)) {
    731                 vectorType = PS_TYPE_S16;
    732             } else if (!strncmp(strType,"S32",3)) {
    733                 vectorType = PS_TYPE_S32;
    734             } else if (!strncmp(strType,"S64",3)) {
    735                 vectorType = PS_TYPE_S64;
    736             } else if (!strncmp(strType,"F32",3)) {
    737                 vectorType = PS_TYPE_F32;
    738             } else if (!strncmp(strType,"F64",3)) {
    739                 vectorType = PS_TYPE_F64;
    740             } else {
    741                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, "", keyName,
    742                         strType, lineCount, fileName);
    743                 psFree(strType);
    744                 return false;
    745             }
    746         } else if(!strncmp(strType, "STR", 3)) {
    747             mdType = PS_META_STR;
    748         } else if(!strncmp(strType, "BOOL", 4)) {
    749             mdType = PS_META_BOOL;
    750         } else if(!strncmp(strType, "S32", 3)) {
    751             mdType = PS_META_S32;
    752         } else if(!strncmp(strType, "F32", 3)) {
    753             mdType = PS_META_F32;
    754         } else if(!strncmp(strType, "F64", 3)) {
    755             mdType = PS_META_F64;
    756         } else if(!strncmp(strType, "MULTI", 5)) {
    757             mdType = PS_META_MULTI;
    758         } else if(!strncmp(strType, "METADATA", 8)) {
    759             mdType = PS_META_META;
    760         } else {
    761             // Search through user types
    762             typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
    763             templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
    764             for(psS32 k = 0; k < typeArray->n; k++) {
    765                 if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
    766                     tempMeta = setMetadataItem((psMetadata*)templateArray->data[k],linePtr);
    767                     if(tempMeta != NULL) {
    768                         // Add metadata item
    769                         md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
    770                         addStatus = psMetadataAdd(md,PS_LIST_TAIL,keyName,PS_META_META | flags,"",tempMeta);
    771                         // Check for add failure
    772                         if (! addStatus) {
    773                             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM,
    774                                     keyName, lineCount, fileName);
    775                             psFree(strType);
    776                             psFree(tempMeta);
    777                             return false;
    778                         }
    779                         psFree(tempMeta);
    780                     } else {
    781                         // Metadata type read error
    782                         psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,
    783                                 keyName,lineCount,fileName);
    784                         psFree(strType);
    785                         return false;
    786                     }
    787                     typeFound = true;
    788                     break;
    789                 }
    790             }
    791             if(!typeFound) {
    792                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
    793                         strType, lineCount,fileName);
    794                 psFree(strType);
    795                 return false;
    796             } else {
    797                 psFree(strType);
    798                 return true;
    799             }
    800         }
    801     }
    802 
    803     // If type is not MULTI or META then get the value and comment
    804     if((mdType != PS_META_MULTI) && (mdType != PS_META_META)) {
    805         // Get the metadata item value if there is one.
    806         status = 0;
    807         strValue = getToken(&linePtr, "#", &status,true);
    808         if(status) {
    809             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
    810                     fileName);
    811             psFree(strType);
    812             psFree(strValue);
    813             return false;
    814         }
    815         if(strValue==NULL) {
    816             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
    817                     fileName);
    818             psFree(strType);
    819             psFree(strValue);
    820             return false;
    821         }
    822         // Not all lines will have comments, so NULL is ok.
    823         status = 0;
    824         strComment = getToken(&linePtr,"~", &status,true);
    825         if(status) {
    826             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
    827                     fileName);
    828             psFree(strType);
    829             psFree(strValue);
    830             psFree(strComment);
    831         }
    832     }
    833 
    834     // Need to add item to metadata so get pointer to metadata
    835     status = 0;
    836     md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
    837     nonUniqueKeys = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray;
    838     switch(mdType) {
    839     case PS_META_STR:
    840         addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
    841                                   mdType | flags,
    842                                   strComment, strValue);
    843         break;
    844     case PS_META_BOOL:
    845         tempBool = parseBool(strValue, &status);
    846         if(!status) {
    847             addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
    848                                       mdType | flags,
    849                                       strComment, tempBool);
    850         } else {
    851             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
    852                     strType, lineCount, fileName);
    853             returnValue = false;
    854         }
    855         break;
    856     case PS_META_F32:
    857     case PS_META_F64:
    858         tempDbl = parseValue(strValue, &status);
    859         if(!status) {
    860             addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
    861                                       mdType | flags,
    862                                       strComment, tempDbl);
    863         } else {
    864             psError(PS_ERR_IO, true,
    865                     PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName, strType, lineCount,
    866                     fileName);
    867             returnValue = false;
    868         }
    869         break;
    870     case PS_META_S32:
    871         tempInt = (psS32)parseValue(strValue, &status);
    872         if(!status) {
    873             addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
    874                                       mdType | flags,
    875                                       strComment, tempInt);
    876         } else {
    877             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
    878                     strType, lineCount, fileName);
    879             returnValue = false;
    880         }
    881         break;
    882     case PS_META_VEC:
    883         tempVec = parseVector(strValue, vectorType, &status);
    884         if(!status) {
    885             addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName+1,
    886                                       mdType | flags,
    887                                       strComment, tempVec);
    888         } else {
    889             psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
    890                     strType, lineCount, fileName);
    891             returnValue = false;
    892         }
    893         psFree(tempVec);
    894         break;
    895     case PS_META_MULTI:
    896         // Add key to non-unique array of keys
    897         // Check for duplicate MULTI lines
    898         addStatus = true;
    899         for(psS32 k=0; k < nonUniqueKeys->n; k++) {
    900             if(strcmp(keyName,(char*)nonUniqueKeys->data[k]) == 0) {
    901                 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_DUPLICATE_MULTI,
    902                         lineCount,fileName);
    903                 psFree(strType);
    904                 return false;
    905             }
    906         }
    907         tempStr = psStringCopy(keyName);
    908         nonUniqueKeys = psArrayAdd(nonUniqueKeys,0,tempStr);
    909         addStatus = true;
    910         psFree(tempStr);
    911         break;
    912     case PS_META_META:
    913         // Create next level info
    914         nextLevelInfo = p_psParseLevelInfoAlloc();
    915         // Create new metadata
    916         nextLevelInfo->metadata = psMetadataAlloc();
    917         // Save name of metadata
    918         nextLevelInfo->name = psStringCopy(keyName);
    919         // Add next level to levelArray
    920         levelArray = psArrayAdd(levelArray,1,nextLevelInfo);
    921         psFree(nextLevelInfo);
    922         // Increment level counter
    923         (*level)++;
    924         addStatus = true;
    925         break;
    926     default:
    927         psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
    928                 lineCount,fileName);
    929         break;
    930     }
    931 
    932     // Check if the add status was successful
    933     if (! addStatus) {
    934         //        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, keyName, lineCount,
    935         //                fileName);
    936         returnValue = false;
    937     }
    938 
    939     psFree(strComment);
    940     psFree(strValue);
    941     psFree(strType);
    942 
    943     return returnValue;
    944 }
    945 
    946 psBool parseLine(psS32* level,     psArray* levelArray, char*  linePtr,
    947                  psS32  lineCount, char*    fileName,   psBool overwrite)
    948 {
    949     psBool              returnValue    = true;
    950     psMetadataFlags     flags          = PS_META_DEFAULT;
    951     char*               keyName        = NULL;
    952     psS32               status         = 0;
    953     psS32               limit          = 0;
    954     psMetadata*         tempTemplate   = NULL;
    955     char*               strType        = NULL;
    956     psArray*            typeArray      = NULL;
    957     psArray*            templateArray  = NULL;
    958     p_psParseLevelInfo* upperLevelInfo = NULL;
    959     p_psParseLevelInfo* lowerLevelInfo = NULL;
    960     psBool              addStatus      = 0;
    961 
    962     // Set flags if overwrite specified
    963     if(overwrite) {
    964         flags = PS_META_REPLACE;
    965     }
    966 
    967     // If line is not a comment or blank, then extract data
    968     if(!ignoreLine(linePtr)) {
    969 
    970         // Check for more than one '@' in a line
    971         if(repeatedChars(linePtr, '@') > 1) {
    972             psError(PS_ERR_IO, true,
    973                     PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);
    974             return false;
    975         }
    976 
    977         // Get metadata item name
    978         keyName = getToken(&linePtr, " ", &status,true);
    979         if(status) {
    980             psError(PS_ERR_IO, true,
    981                     PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "keyName", lineCount, fileName);
    982             psFree(keyName);
    983             return false;
    984         }
    985 
    986         // Check for special keyName values "TYPE", "END"
    987         if(strcmp(keyName,"TYPE") == 0 ) {
    988             // Get the type name
    989             strType = getToken(&linePtr," ",&status,true);
    990             if(strType == NULL) {
    991                 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,"type",lineCount,
    992                         fileName);
    993                 psFree(keyName);
    994                 return false;
    995             }
    996             tempTemplate = getMetadataType(linePtr);
    997             // Check if type was parsed succesfully
    998             if(tempTemplate != NULL) {
    999                 // Access type array
    1000                 typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
    1001                 // Check if type already exists in array
    1002                 for(psS32 k=0; k < typeArray->n; k++) {
    1003                     // Compare type name with the list of current types
    1004                     if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
    1005                         psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_TYPE_DUPLICATE,
    1006                                 strType,lineCount,fileName);
    1007                         psFree(tempTemplate);
    1008                         psFree(keyName);
    1009                         psFree(strType);
    1010                         return false;
    1011                     }
    1012                 }
    1013                 // Add key name to array of type
    1014                 typeArray = psArrayAdd(typeArray,1,strType);
    1015                 // Add template to array of templates
    1016                 templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
    1017                 templateArray = psArrayAdd(templateArray,1,tempTemplate);
    1018                 psFree(tempTemplate);
    1019             } else {
    1020                 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
    1021                         strType,lineCount,fileName);
    1022                 psFree(keyName);
    1023                 psFree(strType);
    1024                 return false;
    1025             }
    1026             psFree(strType);
    1027         } else if (strcmp(keyName,"END") == 0 ) {
    1028             if(*level > 0) {
    1029                 upperLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level-1]));
    1030                 lowerLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level]));
    1031                 // Check name in nonunique list
    1032                 for(psS32 k=0; k < upperLevelInfo->nonUniqueKeyArray->n; k++) {
    1033                     if(strcmp(upperLevelInfo->nonUniqueKeyArray->data[k],lowerLevelInfo->name) == 0) {
    1034                         flags = PS_META_DUPLICATE_OK;
    1035                         break;
    1036                     }
    1037                 }
    1038                 // Add metadata to upper level metadata
    1039                 addStatus = psMetadataAdd(upperLevelInfo->metadata,
    1040                                           PS_LIST_TAIL,lowerLevelInfo->name,
    1041                                           PS_META_META | flags,
    1042                                           "",
    1043                                           lowerLevelInfo->metadata);
    1044                 if(!addStatus) {
    1045                     psFree(keyName);
    1046                     return false;
    1047                 } else {
    1048                     // Remove lower info level
    1049                     if(!psArrayRemove(levelArray,levelArray->data[*level])) {
    1050                         psFree(keyName);
    1051                         return false;
    1052                     }
    1053                     psFree(lowerLevelInfo);
    1054                     (*level)--;
    1055                 }
    1056             } else {
    1057                 psFree(keyName);
    1058                 return false;
    1059             }
    1060         } else {
    1061             // Check if key name present in array of non-unique key names
    1062             limit = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray->n;
    1063             for(psS32 k=0; k < limit; k++) {
    1064                 char* name = (char*)((p_psParseLevelInfo*)
    1065                                      (levelArray->data[*level]))->nonUniqueKeyArray->data[k];
    1066                 if(strcmp(name,keyName) == 0) {
    1067                     flags = PS_META_DUPLICATE_OK;
    1068                 }
    1069             }
    1070             // Parse metadataItem
    1071             if(!parseMetadataItem(keyName,level, levelArray, linePtr, lineCount, fileName, flags)) {
    1072                 psFree(keyName);
    1073                 return false;
    1074             }
    1075         }
    1076         psFree(keyName);
    1077     }
    1078     return returnValue;
    1079 }
    1080 
    1081 psMetadata* psMetadataConfigParse(psMetadata* md, unsigned int *nFail, const char *fileName, bool overwrite)
    1082 {
    1083     FILE*               fp                   = NULL;
    1084     char*               line                 = NULL;
    1085     char*               linePtr              = NULL;
    1086     psArray*            parseLevelInfoArray  = NULL;
    1087     psS32               lineCount            = 0;
    1088     psS32               nestingLevel         = 0;
    1089     p_psParseLevelInfo* topLevelInfo         = NULL;
    1090 
    1091     // Check for NULL file name
    1092     PS_ASSERT_PTR_NON_NULL(fileName,NULL);
    1093 
    1094     // Check for NULL nFail
    1095     PS_ASSERT_PTR_NON_NULL(nFail,NULL);
    1096 
    1097     // Attempt to open specified file
    1098     if((fp=fopen(fileName, "r")) == NULL) {
    1099         psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
    1100         return NULL;
    1101     }
    1102 
    1103     // Allocate metadata if necessary
    1104     if (md == NULL) {
    1105         md = psMetadataAlloc();
    1106     }
    1107 
    1108     // Allocate array to store parse level information
    1109     parseLevelInfoArray = psArrayAlloc(10);
    1110     parseLevelInfoArray->n = 0;
    1111 
    1112     // Set parse level info for the top level
    1113     topLevelInfo = p_psParseLevelInfoAlloc();
    1114     topLevelInfo->metadata = psMemIncrRefCounter(md);
    1115     parseLevelInfoArray = psArrayAdd(parseLevelInfoArray,1,topLevelInfo);
    1116     psFree(topLevelInfo);
    1117 
    1118     // Create reusable line for continuous read
    1119     line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
    1120 
    1121     // While loop to parse the file
    1122     while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
    1123 
    1124         // Initialize variables for new line
    1125         linePtr = line;
    1126         lineCount++;
    1127 
    1128         if(!parseLine(&nestingLevel,parseLevelInfoArray,linePtr,lineCount,(char*)fileName,overwrite)) {
    1129             (*nFail)++;
    1130         }
    1131     }
    1132 
    1133     // Free parse array and line buffer
    1134     psFree(parseLevelInfoArray);
    1135     psFree(line);
    1136 
    1137     return md;
    1138157}
    1139158
Note: See TracChangeset for help on using the changeset viewer.