IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 16, 2005, 9:43:53 AM (21 years ago)
Author:
evanalst
Message:

Bug #392 fix.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/collections/psMetadataIO.c

    r3769 r3945  
    88*
    99*  @author Ross Harman, MHPCC
     10*  @author Eric Van Alst, MHPCC
    1011*
    11 *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
    12 *  @date $Date: 2005-04-26 19:53:30 $
     12*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2005-05-16 19:43:53 $
    1314*
    1415*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3334#include "psConstants.h"
    3435#include "psAstronomyErrors.h"
    35 
    3636
    3737/******************************************************************************/
     
    5353return NULL;
    5454
    55 /** Free and null temporary variables used by config file parser */
    56 #define CLEAR_TEMPS()                                                                                        \
    57 if(strName) {                                                                                                \
    58     psFree(strName);                                                                                         \
    59     strName = NULL;                                                                                          \
    60 }                                                                                                            \
    61 if(strType) {                                                                                                \
    62     psFree(strType);                                                                                         \
    63     strType = NULL;                                                                                          \
    64 }                                                                                                            \
    65 if(strValue) {                                                                                               \
    66     psFree(strValue);                                                                                        \
    67     strValue = NULL;                                                                                         \
    68 }                                                                                                            \
    69 if(strComment) {                                                                                             \
    70     psFree(strComment);                                                                                      \
    71     strComment = NULL;                                                                                       \
    72 }
    73 
    7455/** Maximum size of a FITS line */
    7556#define FITS_LINE_SIZE 80
     
    10586static void initMetadataItemXml(void *ctx, char *tagName);
    10687static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
    107 
    108 /** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
    109  *  must be null terminated. */
     88static psMetadata* getMetadataType(char *linePtr);
     89static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
     90;
     91static void parseLevelInfoFree(p_psParseLevelInfo* info);
     92static psBool parseLine(psS32* level,   psArray* levelArray,
     93                        char*  linePtr, psS32 lineCount,     char* fileName, psBool overwrite);
     94static psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
     95                                char* linePtr, psS32  lineCount, char*    fileName,    psMetadataFlags flags);
     96
     97static 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.
    110108psBool ignoreLine(char *inString)
    111109{
     
    121119
    122120
    123 /** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
    124  *  terminated copy of the original input string. */
    125 char *cleanString(char *inString, psS32 sLen)
     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.
     123char *cleanString(char *inString, psS32 sLen, psBool ignoreComment)
    126124{
    127125    char *ptrB = NULL;
     
    129127    char *cleaned = NULL;
    130128
    131 
     129    // Initialize begining of string pointer
    132130    ptrB = inString;
    133131
    134     /* Skip over leading # or whitespace */
    135     while (isspace(*ptrB) || *ptrB=='#') {
    136         ptrB++;
    137     }
    138 
    139     /* Skip over trailing whitespace, null terminators, and # characters */
     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
    140144    ptrE = inString + sLen;
    141     while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
    142         ptrE--;
     145    if(ignoreComment) {
     146        while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     147            ptrE--;
     148        }
     149    } else {
     150        while(isspace(*ptrE) || *ptrE=='\0') {
     151            ptrE--;
     152        }
    143153    }
    144154
     
    152162}
    153163
    154 /** Count repeat occurances of a single character within a line. The input string must be null terminated. */
     164// Count repeat occurances of a single character within a line. The input string must be null terminated.
    155165psS32 repeatedChars(char *inString, char ch)
    156166{
    157167    psS32 count = 0;
    158 
    159168
    160169    while(*inString!='\0') {
     
    168177}
    169178
    170 /** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
    171  * the beginning of the string. Tokens are newly allocated null terminated strings. */
    172 char* getToken(char **inString, char *delimiter, psS32 *status)
     179// Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
     180// the beginning of the string. Tokens are newly allocated null terminated strings.
     181char* getToken(char **inString, char *delimiter, psS32 *status, psBool ignoreComment)
    173182{
    174183    char *cleanToken = NULL;
     184    char *convertChar = NULL;
    175185    psS32 sLen = 0;
    176186
     187    // Convert tab characters to white space
     188    while((convertChar=strchr(*inString,'\t')) != NULL ) {
     189        *convertChar = ' ';
     190    }
    177191
    178192    // Skip over leading whitespace
     
    186200
    187201        // Create new, cleaned, and null terminated token
    188         cleanToken = cleanString(*inString, sLen);
     202        cleanToken = cleanString(*inString, sLen,ignoreComment);
    189203
    190204        // Move to end of token
     
    197211}
    198212
    199 /** Returns single parsed value as a double precision number. The input string must be cleaned and null
    200  * terminated. */
     213// Returns single parsed value as a double precision number. The input string must be cleaned and null
     214// terminated.
    201215double parseValue(char *inString, psS32 *status)
    202216{
    203217    char *end = NULL;
    204218    double value = 0.0;
    205 
    206219
    207220    value = strtod(inString, &end);
     
    235248psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
    236249{
    237     char *end = NULL;
    238     char *saveValue = NULL;
    239     psS32 i = 0;
    240     psS32 numValues = 0;
    241     double value = 0.0;
    242     psVector *vec = NULL;
    243 
     250    char*      end       = NULL;
     251    char*      saveValue = NULL;
     252    psS32      i         = 0;
     253    psS32      numValues = 0;
     254    double     value     = 0.0;
     255    psVector*  vec       = NULL;
    244256
    245257    // Cycle through string and count entries
     
    274286                vec->data.U8[i++] = (psU8)value;
    275287                break;
     288            case PS_TYPE_U16:
     289                vec->data.U16[i++] = (psU16)value;
     290                break;
     291            case PS_TYPE_U32:
     292                vec->data.U32[i++] = (psU32)value;
     293                break;
     294            case PS_TYPE_U64:
     295                vec->data.U64[i++] = (psU64)value;
     296                break;
     297            case PS_TYPE_S8:
     298                vec->data.S8[i++] = (psS8)value;
     299                break;
     300            case PS_TYPE_S16:
     301                vec->data.S16[i++] = (psS16)value;
     302                break;
    276303            case PS_TYPE_S32:
    277304                vec->data.S32[i++] = (psS32)value;
     305                break;
     306            case PS_TYPE_S64:
     307                vec->data.S64[i++] = (psS64)value;
    278308                break;
    279309            case PS_TYPE_F32:
     
    303333/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
    304334/*****************************************************************************/
     335
     336p_psParseLevelInfo* p_psParseLevelInfoAlloc(void)
     337{
     338
     339    p_psParseLevelInfo* info = NULL;
     340
     341    // Allocate memory for parse level info
     342    info = (p_psParseLevelInfo*)psAlloc(sizeof(p_psParseLevelInfo));
     343
     344    // If allocation successful then initialize members
     345    if(info != NULL) {
     346
     347        info->nonUniqueKeyArray = psArrayAlloc(10);
     348        info->nonUniqueKeyArray->n = 0;
     349
     350        info->typeArray = psArrayAlloc(10);
     351        info->typeArray->n = 0;
     352
     353        info->templateArray = psArrayAlloc(10);
     354        info->templateArray->n = 0;
     355
     356        info->metadata = NULL;
     357        info->name = NULL;
     358
     359        // Set memory deallocator
     360        psMemSetDeallocator(info,(psFreeFcn)parseLevelInfoFree);
     361    }
     362    return info;
     363}
    305364
    306365bool psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* metadataItem)
     
    500559}
    501560
     561static psMetadata* getMetadataType(char* linePtr)
     562{
     563    psMetadata*     metadataTemplate = NULL;
     564    psS32           status           = 0;
     565    char*           token            = NULL;
     566    psMetadataItem* tempItem         = NULL;
     567
     568    // Loop through line and generate metadata items for each token found
     569    while((token = getToken(&linePtr," ",&status,false)) != NULL ) {
     570
     571        // If not allocated then allocate new metadata
     572        if(metadataTemplate == NULL) {
     573            metadataTemplate = psMetadataAlloc();
     574        }
     575
     576        // Look for comment indicator #
     577        if(strstr(token,"#") != 0) {
     578            psFree(token);
     579            break;
     580        }
     581
     582        // Create metadata item to represent token read
     583        tempItem = psMetadataItemAllocStr(token,"","");
     584        if(tempItem == NULL) {
     585            psFree(metadataTemplate);
     586            psFree(token);
     587            metadataTemplate = NULL;
     588            break;
     589        }
     590
     591        // Add item to template
     592        if(!psMetadataAddItem(metadataTemplate, tempItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
     593            psFree(metadataTemplate);
     594            psFree(tempItem);
     595            psFree(token);
     596            metadataTemplate = NULL;
     597            break;
     598        }
     599        psFree(tempItem);
     600        psFree(token);
     601    }
     602
     603    return metadataTemplate;
     604}
     605
     606static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
     607{
     608    psMetadata*      md           = NULL;
     609    psS32            items        = 0;
     610    char*            token        = NULL;
     611    psS32            status       = 0;
     612    psMetadataItem*  mdItem       = NULL;
     613    psMetadataItem*  templateItem = NULL;
     614    psListIterator*  iter         = NULL;
     615
     616    // Determine the number of items in template
     617    items = template->list->size;
     618    if(items > 0 ) {
     619
     620        // Allocate metadata
     621        md = psMetadataAlloc()
     622             ;
     623
     624        // Point to first item in template
     625        iter = psListIteratorAlloc(template->
     626                                   list,PS_LIST_HEAD,true);
     627
     628        // For each item in template parse line string for values
     629        for(psS32 i = 0;
     630                i < items;
     631                i++) {
     632
     633            // Get template item
     634            templateItem = psListGetAndIncrement(iter)
     635                           ;
     636            if(templateItem == NULL) {
     637                psFree(md);
     638                md = NULL;
     639                break;
     640            }
     641
     642            // Get the next token on the line
     643            token = getToken(&linePtr," ",&status,false);
     644            if(token != NULL) {
     645                // Allocate metadata item
     646                mdItem = psMetadataItemAllocStr(templateItem->name,templateItem->comment,token);
     647                if(mdItem == NULL) {
     648                    psFree(md);
     649                    md = NULL;
     650                    psFree(token);
     651                    break;
     652                }
     653                // Add item to metadata
     654                if(!psMetadataAddItem(md, mdItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
     655                    psFree(md);
     656                    md = NULL;
     657                    psFree(mdItem);
     658                    psFree(token);
     659                    break;
     660                }
     661                psFree(mdItem);
     662            } else {
     663                // Missing items
     664                psFree(md);
     665                md = NULL;
     666                break;
     667            }
     668
     669            psFree(token);
     670        }
     671        psFree(iter);
     672    }
     673    return md;
     674}
     675
     676psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
     677                         char* linePtr, psS32  lineCount, char*    fileName,   psMetadataFlags flags)
     678{
     679    psBool               returnValue   = true;
     680    psBool               addStatus     = false;
     681    psMetadataType       mdType        = PS_META_UNKNOWN;
     682    psElemType           vectorType    = PS_TYPE_S8;
     683    char*                strType       = NULL;
     684    char*                strValue      = NULL;
     685    char*                strComment    = NULL;
     686    psS32                status        = 0;
     687    psMetadata*          md            = NULL;
     688    psF64                tempDbl       = 0.0;
     689    psBool               tempBool      = false;
     690    psS32                tempInt       = 0;
     691    psVector*            tempVec       = NULL;
     692    char*                tempStr       = NULL;
     693    psArray*             nonUniqueKeys = NULL;
     694    psBool               typeFound     = false;
     695    psArray*             typeArray     = NULL;
     696    psArray*             templateArray = NULL;
     697    psMetadata*          tempMeta      = NULL;
     698    p_psParseLevelInfo*  nextLevelInfo = NULL;
     699
     700    // Get the metadata item type
     701    strType = getToken(&linePtr, " ", &status,true);
     702
     703    // Check for no type
     704    if(strType==NULL) {
     705        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,
     706                fileName);
     707        returnValue = false;
     708    } else {
     709
     710        // Set metadata type based on type token
     711
     712        // Check if the keyName specifies a vector and if so use strType token to find vector type
     713        if(*keyName == '@') {
     714            mdType = PS_META_VEC;
     715            // Get the type of vector
     716            if(!strncmp(strType, "U8", 2)) {
     717                vectorType = PS_TYPE_U8;
     718            } else if (!strncmp(strType,"U16",3)) {
     719                vectorType = PS_TYPE_U16;
     720            } else if (!strncmp(strType,"U32",3)) {
     721                vectorType = PS_TYPE_U32;
     722            } else if (!strncmp(strType,"U64",3)) {
     723                vectorType = PS_TYPE_U64;
     724            } else if (!strncmp(strType,"S8",2)) {
     725                vectorType = PS_TYPE_S8;
     726            } else if (!strncmp(strType,"S16",3)) {
     727                vectorType = PS_TYPE_S16;
     728            } else if (!strncmp(strType,"S32",3)) {
     729                vectorType = PS_TYPE_S32;
     730            } else if (!strncmp(strType,"S64",3)) {
     731                vectorType = PS_TYPE_S64;
     732            } else if (!strncmp(strType,"F32",3)) {
     733                vectorType = PS_TYPE_F32;
     734            } else if (!strncmp(strType,"F64",3)) {
     735                vectorType = PS_TYPE_F64;
     736            } else {
     737                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, "", keyName,
     738                        strType, lineCount, fileName);
     739                psFree(strType);
     740                return false;
     741            }
     742        } else if(!strncmp(strType, "STR", 3)) {
     743            mdType = PS_META_STR;
     744        } else if(!strncmp(strType, "BOOL", 4)) {
     745            mdType = PS_META_BOOL;
     746        } else if(!strncmp(strType, "S32", 3)) {
     747            mdType = PS_META_S32;
     748        } else if(!strncmp(strType, "F32", 3)) {
     749            mdType = PS_META_F32;
     750        } else if(!strncmp(strType, "F64", 3)) {
     751            mdType = PS_META_F64;
     752        } else if(!strncmp(strType, "MULTI", 5)) {
     753            mdType = PS_META_MULTI;
     754        } else if(!strncmp(strType, "METADATA", 8)) {
     755            mdType = PS_META_META;
     756        } else {
     757            // Search through user types
     758            typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
     759            templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
     760            for(psS32 k = 0; k < typeArray->n; k++) {
     761                if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
     762                    tempMeta = setMetadataItem((psMetadata*)templateArray->data[k],linePtr);
     763                    if(tempMeta != NULL) {
     764                        // Add metadata item
     765                        md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
     766                        addStatus = psMetadataAdd(md,PS_LIST_TAIL,keyName,PS_META_META | flags,"",tempMeta);
     767                        // Check for add failure
     768                        if (! addStatus) {
     769                            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM,
     770                                    keyName, lineCount, fileName);
     771                            psFree(strType);
     772                            psFree(tempMeta);
     773                            return false;
     774                        }
     775                        psFree(tempMeta);
     776                    } else {
     777                        // Metadata type read error
     778                        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,
     779                                keyName,lineCount,fileName);
     780                        psFree(strType);
     781                        return false;
     782                    }
     783                    typeFound = true;
     784                    break;
     785                }
     786            }
     787            if(!typeFound) {
     788                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
     789                        strType, lineCount,fileName);
     790                psFree(strType);
     791                return false;
     792            } else {
     793                psFree(strType);
     794                return true;
     795            }
     796        }
     797    }
     798
     799    // If type is not MULTI or META then get the value and comment
     800    if((mdType != PS_META_MULTI) && (mdType != PS_META_META)) {
     801        // Get the metadata item value if there is one.
     802        status = 0;
     803        strValue = getToken(&linePtr, "#", &status,true);
     804        if(status) {
     805            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
     806                    fileName);
     807            psFree(strType);
     808            psFree(strValue);
     809            return false;
     810        }
     811        if(strValue==NULL) {
     812            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
     813                    fileName);
     814            psFree(strType);
     815            psFree(strValue);
     816            return false;
     817        }
     818        // Not all lines will have comments, so NULL is ok.
     819        status = 0;
     820        strComment = getToken(&linePtr,"~", &status,true);
     821        if(status) {
     822            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
     823                    fileName);
     824            psFree(strType);
     825            psFree(strValue);
     826            psFree(strComment);
     827        }
     828    }
     829
     830    // Need to add item to metadata so get pointer to metadata
     831    status = 0;
     832    md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
     833    nonUniqueKeys = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray;
     834    switch(mdType) {
     835    case PS_META_STR:
     836        addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
     837                                  mdType | flags,
     838                                  strComment, strValue);
     839        break;
     840    case PS_META_BOOL:
     841        tempBool = parseBool(strValue, &status);
     842        if(!status) {
     843            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
     844                                      mdType | flags,
     845                                      strComment, tempBool);
     846        } else {
     847            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
     848                    strType, lineCount, fileName);
     849            returnValue = false;
     850        }
     851        break;
     852    case PS_META_F32:
     853    case PS_META_F64:
     854        tempDbl = parseValue(strValue, &status);
     855        if(!status) {
     856            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
     857                                      mdType | flags,
     858                                      strComment, tempDbl);
     859        } else {
     860            psError(PS_ERR_IO, true,
     861                    PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName, strType, lineCount,
     862                    fileName);
     863            returnValue = false;
     864        }
     865        break;
     866    case PS_META_S32:
     867        tempInt = (psS32)parseValue(strValue, &status);
     868        if(!status) {
     869            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
     870                                      mdType | flags,
     871                                      strComment, tempInt);
     872        } else {
     873            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
     874                    strType, lineCount, fileName);
     875            returnValue = false;
     876        }
     877        break;
     878    case PS_META_VEC:
     879        tempVec = parseVector(strValue, vectorType, &status);
     880        if(!status) {
     881            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName+1,
     882                                      mdType | flags,
     883                                      strComment, tempVec);
     884        } else {
     885            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
     886                    strType, lineCount, fileName);
     887            returnValue = false;
     888        }
     889        psFree(tempVec);
     890        break;
     891    case PS_META_MULTI:
     892        // Add key to non-unique array of keys
     893        // Check for duplicate MULTI lines
     894        addStatus = true;
     895        for(psS32 k=0; k < nonUniqueKeys->n; k++) {
     896            if(strcmp(keyName,(char*)nonUniqueKeys->data[k]) == 0) {
     897                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_DUPLICATE_MULTI,
     898                        lineCount,fileName);
     899                psFree(strType);
     900                return false;
     901            }
     902        }
     903        tempStr = psStringCopy(keyName);
     904        nonUniqueKeys = psArrayAdd(nonUniqueKeys,0,tempStr);
     905        addStatus = true;
     906        psFree(tempStr);
     907        break;
     908    case PS_META_META:
     909        // Create next level info
     910        nextLevelInfo = p_psParseLevelInfoAlloc();
     911        // Create new metadata
     912        nextLevelInfo->metadata = psMetadataAlloc();
     913        // Save name of metadata
     914        nextLevelInfo->name = psStringCopy(keyName);
     915        // Add next level to levelArray
     916        levelArray = psArrayAdd(levelArray,1,nextLevelInfo);
     917        psFree(nextLevelInfo);
     918        // Increment level counter
     919        (*level)++;
     920        addStatus = true;
     921        break;
     922    default:
     923        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
     924                lineCount,fileName);
     925        break;
     926    }
     927
     928    // Check if the add status was successful
     929    if (! addStatus) {
     930        //        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, keyName, lineCount,
     931        //                fileName);
     932        returnValue = false;
     933    }
     934
     935    psFree(strComment);
     936    psFree(strValue);
     937    psFree(strType);
     938
     939    return returnValue;
     940}
     941
     942psBool parseLine(psS32* level,     psArray* levelArray, char*  linePtr,
     943                 psS32  lineCount, char*    fileName,   psBool overwrite)
     944{
     945    psBool              returnValue    = true;
     946    psMetadataFlags     flags          = PS_META_DEFAULT;
     947    char*               keyName        = NULL;
     948    psS32               status         = 0;
     949    psS32               limit          = 0;
     950    psMetadata*         tempTemplate   = NULL;
     951    char*               strType        = NULL;
     952    psArray*            typeArray      = NULL;
     953    psArray*            templateArray  = NULL;
     954    p_psParseLevelInfo* upperLevelInfo = NULL;
     955    p_psParseLevelInfo* lowerLevelInfo = NULL;
     956    psBool              addStatus      = 0;
     957
     958    // Set flags if overwrite specified
     959    if(overwrite) {
     960        flags = PS_META_REPLACE;
     961    }
     962
     963    // If line is not a comment or blank, then extract data
     964    if(!ignoreLine(linePtr)) {
     965
     966        // Check for more than one '@' in a line
     967        if(repeatedChars(linePtr, '@') > 1) {
     968            psError(PS_ERR_IO, true,
     969                    PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);
     970            return false;
     971        }
     972
     973        // Get metadata item name
     974        keyName = getToken(&linePtr, " ", &status,true);
     975        if(status) {
     976            psError(PS_ERR_IO, true,
     977                    PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "keyName", lineCount, fileName);
     978            psFree(keyName);
     979            return false;
     980        }
     981
     982        // Check for special keyName values "TYPE", "END"
     983        if(strcmp(keyName,"TYPE") == 0 ) {
     984            // Get the type name
     985            strType = getToken(&linePtr," ",&status,true);
     986            if(strType == NULL) {
     987                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,"type",lineCount,
     988                        fileName);
     989                psFree(keyName);
     990                return false;
     991            }
     992            tempTemplate = getMetadataType(linePtr);
     993            // Check if type was parsed succesfully
     994            if(tempTemplate != NULL) {
     995                // Access type array
     996                typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
     997                // Check if type already exists in array
     998                for(psS32 k=0; k < typeArray->n; k++) {
     999                    // Compare type name with the list of current types
     1000                    if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
     1001                        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_TYPE_DUPLICATE,
     1002                                strType,lineCount,fileName);
     1003                        psFree(tempTemplate);
     1004                        psFree(keyName);
     1005                        psFree(strType);
     1006                        return false;
     1007                    }
     1008                }
     1009                // Add key name to array of type
     1010                typeArray = psArrayAdd(typeArray,1,strType);
     1011                // Add template to array of templates
     1012                templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
     1013                templateArray = psArrayAdd(templateArray,1,tempTemplate);
     1014                psFree(tempTemplate);
     1015            } else {
     1016                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
     1017                        strType,lineCount,fileName);
     1018                psFree(keyName);
     1019                psFree(strType);
     1020                return false;
     1021            }
     1022            psFree(strType);
     1023        } else if (strcmp(keyName,"END") == 0 ) {
     1024            if(*level > 0) {
     1025                upperLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level-1]));
     1026                lowerLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level]));
     1027                // Check name in nonunique list
     1028                for(psS32 k=0; k < upperLevelInfo->nonUniqueKeyArray->n; k++) {
     1029                    if(strcmp(upperLevelInfo->nonUniqueKeyArray->data[k],lowerLevelInfo->name) == 0) {
     1030                        flags = PS_META_DUPLICATE_OK;
     1031                        break;
     1032                    }
     1033                }
     1034                // Add metadata to upper level metadata
     1035                addStatus = psMetadataAdd(upperLevelInfo->metadata,
     1036                                          PS_LIST_TAIL,lowerLevelInfo->name,
     1037                                          PS_META_META | flags,
     1038                                          "",
     1039                                          lowerLevelInfo->metadata);
     1040                if(!addStatus) {
     1041                    psFree(keyName);
     1042                    return false;
     1043                } else {
     1044                    // Remove lower info level
     1045                    if(!psArrayRemove(levelArray,levelArray->data[*level])) {
     1046                        psFree(keyName);
     1047                        return false;
     1048                    }
     1049                    psFree(lowerLevelInfo);
     1050                    (*level)--;
     1051                }
     1052            } else {
     1053                psFree(keyName);
     1054                return false;
     1055            }
     1056        } else {
     1057            // Check if key name present in array of non-unique key names
     1058            limit = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray->n;
     1059            for(psS32 k=0; k < limit; k++) {
     1060                char* name = (char*)((p_psParseLevelInfo*)
     1061                                     (levelArray->data[*level]))->nonUniqueKeyArray->data[k];
     1062                if(strcmp(name,keyName) == 0) {
     1063                    flags = PS_META_DUPLICATE_OK;
     1064                }
     1065            }
     1066            // Parse metadataItem
     1067            if(!parseMetadataItem(keyName,level, levelArray, linePtr, lineCount, fileName, flags)) {
     1068                psFree(keyName);
     1069                return false;
     1070            }
     1071        }
     1072        psFree(keyName);
     1073    }
     1074    return returnValue;
     1075}
     1076
    5021077psMetadata* psMetadataParseConfig(psMetadata* md, psU32 *nFail, const char *fileName, psBool overwrite)
    5031078{
    504     psBool tempBool;
    505     char *line = NULL;
    506     char *strName = NULL;
    507     char *strType = NULL;
    508     char *strValue = NULL;
    509     char *strComment = NULL;
    510     char *linePtr = NULL;
    511     psElemType vecType = 0;
    512     psS32 status = 0;
    513     psU32 lineCount = 0;
    514     psF64 tempDbl = 0.0;
    515     psS32 tempInt = 0.0;
    516     psVector *tempVec = NULL;
    517     FILE *fp = NULL;
    518     psMetadataType mdType;
    519     psMetadataFlags flags;
    520     psBool addStatus;
    521 
    522     // Check for nulls
     1079    FILE*               fp                   = NULL;
     1080    char*               line                 = NULL;
     1081    char*               linePtr              = NULL;
     1082    psArray*            parseLevelInfoArray  = NULL;
     1083    psS32               lineCount            = 0;
     1084    psS32               nestingLevel         = 0;
     1085    p_psParseLevelInfo* topLevelInfo         = NULL;
     1086
     1087    // Check for NULL file name
    5231088    PS_PTR_CHECK_NULL(fileName,NULL);
     1089
     1090    // Check for NULL nFail
     1091    PS_PTR_CHECK_NULL(nFail,NULL);
     1092
     1093    // Attempt to open specified file
    5241094    if((fp=fopen(fileName, "r")) == NULL) {
    5251095        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
     
    5321102    }
    5331103
     1104    // Allocate array to store parse level information
     1105    parseLevelInfoArray = psArrayAlloc(10);
     1106    parseLevelInfoArray->n = 0;
     1107
     1108    // Set parse level info for the top level
     1109    topLevelInfo = p_psParseLevelInfoAlloc();
     1110    topLevelInfo->metadata = psMemIncrRefCounter(md);
     1111    parseLevelInfoArray = psArrayAdd(parseLevelInfoArray,1,topLevelInfo);
     1112    psFree(topLevelInfo);
     1113
    5341114    // Create reusable line for continuous read
    5351115    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     
    5411121        linePtr = line;
    5421122        lineCount++;
    543         CLEAR_TEMPS();
    544 
    545         // If line is not a comment or blank, then extract data
    546         if(!ignoreLine(linePtr)) {
    547 
    548             // Check for more than one '*' or '@' in a line
    549             if(repeatedChars(linePtr, '@') > 1) {
    550                 (*nFail)++;
    551                 psError(PS_ERR_IO, true,
    552                         PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);
    553                 continue;
    554             } else if(repeatedChars(linePtr, '*') > 1) {
    555                 (*nFail)++;
    556                 psError(PS_ERR_IO, true,
    557                         PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '*', lineCount, fileName);
    558                 continue;
    559             } else if(repeatedChars(linePtr, '~') > 0) {
    560                 (*nFail)++;
    561                 psError(PS_ERR_IO, true,
    562                         PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '~', lineCount, fileName);
    563                 continue;
    564             }
    565 
    566             // Get metadata item name
    567             strName = getToken(&linePtr, " ", &status);
    568             if(strName==NULL || status) {
    569                 (*nFail)++;
    570                 status = 0;
    571                 psError(PS_ERR_IO, true,
    572                         PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "name", lineCount, fileName);
    573                 continue;
    574             }
    575 
    576             flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
    577 
    578             // Get the metadata item type
    579             strType = getToken(&linePtr, " ", &status);
    580             if(strType==NULL) {
    581                 (*nFail)++;
    582                 status = 0;
    583                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,
    584                         fileName);
    585                 continue;
    586             } else {
    587                 char* tempStrType = strType;
    588                 if(*strType == '*') {
    589                     flags = PS_META_DUPLICATE_OK;
    590                     tempStrType = strType+1;
    591                 }
    592 
    593                 if(!strncmp(tempStrType, "STR", 3)) {
    594                     mdType = PS_META_STR;
    595                 } else if(!strncmp(tempStrType, "BOOL", 4)) {
    596                     mdType = PS_META_BOOL;
    597                 } else if(!strncmp(tempStrType, "S32", 3)) {
    598                     mdType = PS_META_S32;
    599                 } else if(!strncmp(tempStrType, "F32", 3)) {
    600                     mdType = PS_META_F32;
    601                 } else if(!strncmp(tempStrType, "F64", 3)) {
    602                     mdType = PS_META_F64;
    603                 } else {
    604                     (*nFail)++;
    605                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
    606                             fileName);
    607                     continue;
    608                 }
    609             }
    610 
    611             if(*strName == '@') {
    612                 vecType = PS_META_PRIMITIVE_TYPE(mdType);
    613                 mdType = PS_META_VEC;
    614             }
    615 
    616             // Get the metadata item value if there is one.
    617             strValue = getToken(&linePtr, "#", &status);
    618             if(status) {
    619                 (*nFail)++;
    620                 status = 0;
    621                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
    622                         fileName);
    623                 continue;
    624             }
    625             if(strValue==NULL) {
    626                 (*nFail)++;
    627                 status = 0;
    628                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
    629                         fileName);
    630                 continue;
    631             }
    632 
    633             // Not all lines will have comments, so NULL is ok.
    634             strComment = getToken(&linePtr,"~", &status);
    635             if(status) {
    636                 (*nFail)++;
    637                 status = 0;
    638                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
    639                         fileName);
    640                 continue;
    641             }
    642 
    643             // Create and add metadata item to metadata and parse values
    644             switch (mdType) {
    645             case PS_META_STR:
    646                 addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
    647                                           mdType | flags,
    648                                           strComment, strValue);
    649                 break;
    650             case PS_META_VEC:
    651                 tempVec = parseVector(strValue, vecType, &status);
    652                 if(!status) {
    653                     addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
    654                                               mdType | flags,
    655                                               strComment, tempVec);
    656                 } else {
    657                     status = 0;
    658                     (*nFail)++;
    659                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
    660                             strType, lineCount, fileName);
    661                     continue;
    662                 }
    663                 psFree(tempVec);
    664                 break;
    665             case PS_META_BOOL:
    666                 tempBool = parseBool(strValue, &status);
    667                 if(!status) {
    668                     addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
    669                                               mdType | flags,
    670                                               strComment, tempBool);
    671                 } else {
    672                     status = 0;
    673                     (*nFail)++;
    674                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
    675                             strType, lineCount, fileName);
    676                     continue;
    677                 }
    678                 break;
    679             case PS_META_S32:
    680                 tempInt = (psS32)parseValue(strValue, &status);
    681                 if(!status) {
    682                     addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
    683                                               mdType | flags,
    684                                               strComment, tempInt);
    685                 } else {
    686                     status = 0;
    687                     (*nFail)++;
    688                     psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
    689                             strType, lineCount, fileName);
    690                     continue;
    691                 }
    692                 break;
    693             case PS_META_F32:
    694             case PS_META_F64:
    695                 tempDbl = parseValue(strValue, &status);
    696                 if(!status) {
    697                     addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
    698                                               mdType | flags,
    699                                               strComment, tempDbl);
    700                 } else {
    701                     status = 0;
    702                     (*nFail)++;
    703                     psError(PS_ERR_IO, true,
    704                             PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, lineCount,
    705                             fileName);
    706                     continue;
    707                 }
    708                 break;
    709             default:
    710                 (*nFail)++;
    711                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, mdType, lineCount,
    712                         fileName);
    713                 continue;
    714             } // switch
    715             if (! addStatus) {
    716                 (*nFail)++;
    717                 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
    718                         fileName);
    719             }
    720 
    721         } // if ignoreLine
    722     } // while loop
    723 
     1123
     1124        if(!parseLine(&nestingLevel,parseLevelInfoArray,linePtr,lineCount,(char*)fileName,overwrite)) {
     1125            (*nFail)++;
     1126        }
     1127    }
     1128
     1129    // Free parse array and line buffer
     1130    psFree(parseLevelInfoArray);
    7241131    psFree(line);
    7251132
     1133    // Check if any failed lined detected
     1134    if( (*nFail) != 0) {
     1135        psFree(md);
     1136        md = NULL;
     1137    }
    7261138    return md;
    7271139}
     1140
    7281141
    7291142static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
     
    7501163
    7511164    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
    752     psTagName = psStringCopy((const char*)tagName);
     1165    psTagName = psStringCopy(tagName);
    7531166
    7541167    // Metadata containter for housing element attributes used by other SAX events
     
    7741187
    7751188                // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
    776                 psAttName = psStringCopy((const char*)attName);
    777                 psAttValue = psStringCopy((const char*)attValue);
     1189                psAttName = psStringCopy(attName);
     1190                psAttValue = psStringCopy(attValue);
    7781191                psHashAdd(htAtts, psAttName, psAttValue);
    7791192                psFree(psAttName);
     
    10821495
    10831496    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
    1084     psEndTagName = psStringCopy((const char*)tagName);
     1497    psEndTagName = psStringCopy(tagName);
    10851498
    10861499    // Compare start and end tag names
Note: See TracChangeset for help on using the changeset viewer.