IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 3945


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

Bug #392 fix.

Location:
trunk/psLib
Files:
3 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/astronomy/psAstronomyErrors.dat

    r3441 r3945  
    6666psMetadataIO_TAG_MISMATCH              Start tag, %s and end tag, %s do not agree.
    6767psMetadataIO_TAG_UNKNOWN               Invalid end tag name, %s.
    68 
     68psMetadataIO_TYPE_DUPLICATE            Specified type, %s, on line %u of %s is already defined.
     69psMetadataIO_DUPLICATE_MULTI           Duplicate MULTI specifier on line %u of %s.
  • trunk/psLib/src/astronomy/psAstronomyErrors.h

    r3441 r3945  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2005-03-17 19:01:01 $
     9 *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2005-05-16 19:43:06 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    8383#define PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH "Start tag, %s and end tag, %s do not agree."
    8484#define PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN "Invalid end tag name, %s."
     85#define PS_ERRORTEXT_psMetadataIO_TYPE_DUPLICATE "Specified type, %s, on line %u of %s is already defined."
     86#define PS_ERRORTEXT_psMetadataIO_DUPLICATE_MULTI "Duplicate MULTI specifier on line %u of %s."
    8587//~End
    8688
  • trunk/psLib/src/collections/psMetadata.c

    r3780 r3945  
    1212*  @author Ross Harman, MHPCC
    1313*
    14 *  @version $Revision: 1.61 $ $Name: not supported by cvs2svn $
    15 *  @date $Date: 2005-04-28 19:52:48 $
     14*  @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
     15*  @date $Date: 2005-05-16 19:43:53 $
    1616*
    1717*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3838#include "psAstronomyErrors.h"
    3939#include "psConstants.h"
     40#include "psLogMsg.h"
     41
     42/******************************************************************************/
     43/*  DEFINE STATEMENTS                                                         */
     44/******************************************************************************/
     45
     46/** Maximum size of a string */
     47#define MAX_STRING_LENGTH 1024
     48
     49/******************************************************************************/
     50/*  TYPE DEFINITIONS                                                          */
     51/******************************************************************************/
     52
     53// None
     54
     55/*****************************************************************************/
     56/*  GLOBAL VARIABLES                                                         */
     57/*****************************************************************************/
     58
     59// None
     60
     61/*****************************************************************************/
     62/*  FILE STATIC VARIABLES                                                    */
     63/*****************************************************************************/
    4064
    4165static psS32 metadataId = 0;
     66
     67/*****************************************************************************/
     68/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
     69/*****************************************************************************/
    4270
    4371static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
     
    4876    }
    4977
     78    // move any existing entry into a psList
     79    psList* newList = psListAlloc(existing);
    5080
    5181    psMetadataItem* item = psMetadataItemAlloc(key,
    5282                           PS_META_MULTI,
    53                            "List of Metadata Items",
    54                            NULL);
    55 
    56     psListAdd(item->data.list,PS_LIST_TAIL,existing);
     83                           "",
     84                           newList);
    5785
    5886    if (existing != NULL) {
     
    6088    }
    6189
    62     psHashAdd(table, key, item); // put in the new MULTI list entry
    63 
    64     // free local references of newly allocated item.
     90    psHashAdd(table, key, item); // put in the new entry
     91
     92    // free local references of newly allocated items.
     93    psFree(newList);
    6594    psFree(item);
    6695
     
    80109    psFree(metadataItem->name);
    81110    psFree(metadataItem->comment);
    82     if (! PS_META_IS_PRIMITIVE(type)) {
     111
     112    if(!PS_META_IS_PRIMITIVE(type)) {
    83113        psFree(metadataItem->data.V);
    84114    }
     
    104134    psFree(metadata->list);
    105135    psFree(metadata->table);
     136
    106137}
    107138
     
    146177{
    147178    psMetadataItem* metadataItem = NULL;
    148     char tmp;
    149     int nBytes;
     179
    150180
    151181    PS_PTR_CHECK_NULL(name,NULL);
     
    158188    psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
    159189
    160     // set metadata item comment
     190    // Allocate and set metadata item comment
     191    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
    161192    if (comment == NULL) {
    162193        // Per SDRS, null isn't allowed, must use "" instead
    163         metadataItem->comment = psStringCopy("");
     194        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
    164195    } else {
    165         metadataItem->comment = psStringCopy(comment);
     196        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
    166197    }
    167198
     
    173204
    174205    // Allocate and set metadata item name
    175     nBytes = vsnprintf(&tmp, 0, name, argPtr) + 1;
    176     metadataItem->name = (char *)psAlloc(sizeof(char) * nBytes);
     206    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
    177207    vsprintf(metadataItem->name, name, argPtr);
    178208
     
    193223    case PS_META_STR:
    194224        // Perform copy of input strings
    195         metadataItem->data.V = psStringCopy(va_arg(argPtr, char *));
    196         break;
    197     case PS_META_MULTI:
    198         // MULTI needs to create a psList entry, value must be NULL
    199         metadataItem->data.list = psListAlloc(NULL);
     225        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
    200226        break;
    201227    case PS_META_LIST:
     
    207233    case PS_META_ASTROM:
    208234    case PS_META_UNKNOWN:
     235    case PS_META_META:
     236    case PS_META_MULTI:
    209237        // Copy of input data not performed due to variability of data types
    210238        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
     
    258286
    259287    // See if key is already in table
    260     existingEntry = psMetadataLookup(md, key);
    261 
    262     // if replace is set, remove any existing items of the same key
    263     if (existingEntry != NULL && (flags & PS_META_REPLACE) != 0) {
    264         psMetadataRemove(md,0,key);
    265         existingEntry = NULL;
    266     }
    267 
    268     // if the metadataItem is MULTI, just create a MULTI node.
     288    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
     289
    269290    if (metadataItem->type == PS_META_MULTI) {
    270         if (metadataItem->data.list == NULL || metadataItem->data.list->size > 0) {
    271             psError(PS_ERR_BAD_PARAMETER_VALUE,true,
    272                     "Specified PS_META_MULTI item is not defined properly "
    273                     "(list allocated with zero size).");
    274             return false;
    275         }
    276 
    277         // make sure the existing entry is PS_META_MULTI
     291        // the incoming entry is PS_META_MULTI
     292
     293        // force the hash entry to be PS_META_MULTI
    278294        existingEntry = makeMetaMulti(mdTable,key,existingEntry);
    279295
     296        // add all the items in the incoming entry to metadata
     297        psList* list = metadataItem->data.list;
     298        if (list != NULL) {
     299            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
     300            psMetadataItem* listItem;
     301            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
     302                psMetadataAddItem(md,listItem,location,flags);
     303            }
     304            psFree(iter);
     305        }
     306
    280307        return true; // all done.
    281308    }
    282309
    283310    // how the item is added to the hash depends on prior existence, flags, etc.
    284     if(existingEntry == NULL) { // no prior existence
    285         // Node doesn't already exist - Add new metadata item to metadata collection's hash
    286         if(!psHashAdd(mdTable, key, metadataItem)) {
    287             psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
    288             return false;
    289         }
    290     } else {
     311    if(existingEntry != NULL) { // prior existence
    291312        if (existingEntry->type == PS_META_MULTI || (flags & PS_META_DUPLICATE_OK) != 0) {
    292313            // duplicate entries allowed - add another entry.
    293314
    294             // make sure the existing hash entry is PS_META_MULTI
     315            // make sure the existing entry is PS_META_MULTI
    295316            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
    296317
    297             // add to the hash key's list of entries
     318            // add to the hash's list of duplicate entries
    298319            if (! psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem) ) {
    299320                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
    300321                return false;
    301322            }
     323        } else if ((flags & PS_META_REPLACE) != 0) {
     324            // replace entry instead of creating a duplicate entry.
     325
     326            // remove the existing entry from metadata
     327            psMetadataRemove(md,0,key);
     328
     329            // treat as if new (added to list below)
     330            if(!psHashAdd(mdTable, key, metadataItem)) {
     331                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
     332                return false;
     333            }
     334
     335            // Generate warning that item has been replaced
     336            psLogMsg(__func__,PS_LOG_WARN,"Metadata item %s has been replaced",
     337                     existingEntry->name);
    302338        } else {
    303             // error on duplicate entry.
     339            // default is to error on duplicate entry.
    304340            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    305341                    PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
    306342            return false;
    307343        }
    308     }
    309 
    310     // finally, add the metadataItem to the metadata's list.
     344    } else {
     345        // OK, this is a new item.
     346
     347        // Node doesn't exist - Add new metadata item to metadata collection's hash
     348        if(!psHashAdd(mdTable, key, metadataItem)) {
     349            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
     350            return false;
     351        }
     352    }
     353
    311354    if(!psListAdd(mdList, location, metadataItem)) {
    312355        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
     
    363406METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_META_LOOKUPTABLE)
    364407METADATA_ADD_TYPE(Unknown,void*,PS_META_UNKNOWN)
     408METADATA_ADD_TYPE(Metadata,psMetadata*,PS_META_META)
    365409
    366410psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
  • trunk/psLib/src/collections/psMetadata.h

    r3684 r3945  
    1111*  @author Ross Harman, MHPCC
    1212*
    13 *  @version $Revision: 1.44 $ $Name: not supported by cvs2svn $
    14 *  @date $Date: 2005-04-08 17:58:57 $
     13*  @version $Revision: 1.45 $ $Name: not supported by cvs2svn $
     14*  @date $Date: 2005-05-16 19:43:53 $
    1515*
    1616*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    5151    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
    5252    PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
    53     PS_META_MULTI                      ///< Used internally, do not create an metadata item of this type.
     53    PS_META_MULTI,                     ///< Used internally, do not create an metadata item of this type.
     54    PS_META_META                       ///< Metadata data (Stored as item.data.md).
    5455} psMetadataType;
    5556
     
    105106}
    106107psMetadataIterator;
    107 
    108108
    109109/** Metadata item data structure.
     
    316316psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
    317317                            const char* comment, psPtr value);
     318psBool psMetadataAddMetadata(psMetadata* md, psS32 location, const char* name,
     319                             const char* comment, psMetadata* value);
    318320
    319321/** Remove an item from metadata collection.
  • 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
  • trunk/psLib/src/collections/psMetadataIO.h

    r3381 r3945  
    1010 *  @author Robert DeSonia, MHPCC
    1111 *
    12  *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-03-07 20:58:50 $
     12 *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-05-16 19:43:53 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2121/// @{
    2222
     23typedef struct
     24{
     25    psArray*    nonUniqueKeyArray;
     26    psArray*    typeArray;
     27    psArray*    templateArray;
     28    psMetadata* metadata;
     29    char*       name;
     30}
     31p_psParseLevelInfo;
     32
     33p_psParseLevelInfo* p_psParseLevelInfoAlloc(void);
    2334
    2435/** Print metadata item to file.
  • trunk/psLib/src/types/psMetadata.c

    r3780 r3945  
    1212*  @author Ross Harman, MHPCC
    1313*
    14 *  @version $Revision: 1.61 $ $Name: not supported by cvs2svn $
    15 *  @date $Date: 2005-04-28 19:52:48 $
     14*  @version $Revision: 1.62 $ $Name: not supported by cvs2svn $
     15*  @date $Date: 2005-05-16 19:43:53 $
    1616*
    1717*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3838#include "psAstronomyErrors.h"
    3939#include "psConstants.h"
     40#include "psLogMsg.h"
     41
     42/******************************************************************************/
     43/*  DEFINE STATEMENTS                                                         */
     44/******************************************************************************/
     45
     46/** Maximum size of a string */
     47#define MAX_STRING_LENGTH 1024
     48
     49/******************************************************************************/
     50/*  TYPE DEFINITIONS                                                          */
     51/******************************************************************************/
     52
     53// None
     54
     55/*****************************************************************************/
     56/*  GLOBAL VARIABLES                                                         */
     57/*****************************************************************************/
     58
     59// None
     60
     61/*****************************************************************************/
     62/*  FILE STATIC VARIABLES                                                    */
     63/*****************************************************************************/
    4064
    4165static psS32 metadataId = 0;
     66
     67/*****************************************************************************/
     68/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
     69/*****************************************************************************/
    4270
    4371static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
     
    4876    }
    4977
     78    // move any existing entry into a psList
     79    psList* newList = psListAlloc(existing);
    5080
    5181    psMetadataItem* item = psMetadataItemAlloc(key,
    5282                           PS_META_MULTI,
    53                            "List of Metadata Items",
    54                            NULL);
    55 
    56     psListAdd(item->data.list,PS_LIST_TAIL,existing);
     83                           "",
     84                           newList);
    5785
    5886    if (existing != NULL) {
     
    6088    }
    6189
    62     psHashAdd(table, key, item); // put in the new MULTI list entry
    63 
    64     // free local references of newly allocated item.
     90    psHashAdd(table, key, item); // put in the new entry
     91
     92    // free local references of newly allocated items.
     93    psFree(newList);
    6594    psFree(item);
    6695
     
    80109    psFree(metadataItem->name);
    81110    psFree(metadataItem->comment);
    82     if (! PS_META_IS_PRIMITIVE(type)) {
     111
     112    if(!PS_META_IS_PRIMITIVE(type)) {
    83113        psFree(metadataItem->data.V);
    84114    }
     
    104134    psFree(metadata->list);
    105135    psFree(metadata->table);
     136
    106137}
    107138
     
    146177{
    147178    psMetadataItem* metadataItem = NULL;
    148     char tmp;
    149     int nBytes;
     179
    150180
    151181    PS_PTR_CHECK_NULL(name,NULL);
     
    158188    psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
    159189
    160     // set metadata item comment
     190    // Allocate and set metadata item comment
     191    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
    161192    if (comment == NULL) {
    162193        // Per SDRS, null isn't allowed, must use "" instead
    163         metadataItem->comment = psStringCopy("");
     194        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
    164195    } else {
    165         metadataItem->comment = psStringCopy(comment);
     196        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
    166197    }
    167198
     
    173204
    174205    // Allocate and set metadata item name
    175     nBytes = vsnprintf(&tmp, 0, name, argPtr) + 1;
    176     metadataItem->name = (char *)psAlloc(sizeof(char) * nBytes);
     206    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
    177207    vsprintf(metadataItem->name, name, argPtr);
    178208
     
    193223    case PS_META_STR:
    194224        // Perform copy of input strings
    195         metadataItem->data.V = psStringCopy(va_arg(argPtr, char *));
    196         break;
    197     case PS_META_MULTI:
    198         // MULTI needs to create a psList entry, value must be NULL
    199         metadataItem->data.list = psListAlloc(NULL);
     225        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
    200226        break;
    201227    case PS_META_LIST:
     
    207233    case PS_META_ASTROM:
    208234    case PS_META_UNKNOWN:
     235    case PS_META_META:
     236    case PS_META_MULTI:
    209237        // Copy of input data not performed due to variability of data types
    210238        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
     
    258286
    259287    // See if key is already in table
    260     existingEntry = psMetadataLookup(md, key);
    261 
    262     // if replace is set, remove any existing items of the same key
    263     if (existingEntry != NULL && (flags & PS_META_REPLACE) != 0) {
    264         psMetadataRemove(md,0,key);
    265         existingEntry = NULL;
    266     }
    267 
    268     // if the metadataItem is MULTI, just create a MULTI node.
     288    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
     289
    269290    if (metadataItem->type == PS_META_MULTI) {
    270         if (metadataItem->data.list == NULL || metadataItem->data.list->size > 0) {
    271             psError(PS_ERR_BAD_PARAMETER_VALUE,true,
    272                     "Specified PS_META_MULTI item is not defined properly "
    273                     "(list allocated with zero size).");
    274             return false;
    275         }
    276 
    277         // make sure the existing entry is PS_META_MULTI
     291        // the incoming entry is PS_META_MULTI
     292
     293        // force the hash entry to be PS_META_MULTI
    278294        existingEntry = makeMetaMulti(mdTable,key,existingEntry);
    279295
     296        // add all the items in the incoming entry to metadata
     297        psList* list = metadataItem->data.list;
     298        if (list != NULL) {
     299            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
     300            psMetadataItem* listItem;
     301            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
     302                psMetadataAddItem(md,listItem,location,flags);
     303            }
     304            psFree(iter);
     305        }
     306
    280307        return true; // all done.
    281308    }
    282309
    283310    // how the item is added to the hash depends on prior existence, flags, etc.
    284     if(existingEntry == NULL) { // no prior existence
    285         // Node doesn't already exist - Add new metadata item to metadata collection's hash
    286         if(!psHashAdd(mdTable, key, metadataItem)) {
    287             psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
    288             return false;
    289         }
    290     } else {
     311    if(existingEntry != NULL) { // prior existence
    291312        if (existingEntry->type == PS_META_MULTI || (flags & PS_META_DUPLICATE_OK) != 0) {
    292313            // duplicate entries allowed - add another entry.
    293314
    294             // make sure the existing hash entry is PS_META_MULTI
     315            // make sure the existing entry is PS_META_MULTI
    295316            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
    296317
    297             // add to the hash key's list of entries
     318            // add to the hash's list of duplicate entries
    298319            if (! psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem) ) {
    299320                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
    300321                return false;
    301322            }
     323        } else if ((flags & PS_META_REPLACE) != 0) {
     324            // replace entry instead of creating a duplicate entry.
     325
     326            // remove the existing entry from metadata
     327            psMetadataRemove(md,0,key);
     328
     329            // treat as if new (added to list below)
     330            if(!psHashAdd(mdTable, key, metadataItem)) {
     331                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
     332                return false;
     333            }
     334
     335            // Generate warning that item has been replaced
     336            psLogMsg(__func__,PS_LOG_WARN,"Metadata item %s has been replaced",
     337                     existingEntry->name);
    302338        } else {
    303             // error on duplicate entry.
     339            // default is to error on duplicate entry.
    304340            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    305341                    PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
    306342            return false;
    307343        }
    308     }
    309 
    310     // finally, add the metadataItem to the metadata's list.
     344    } else {
     345        // OK, this is a new item.
     346
     347        // Node doesn't exist - Add new metadata item to metadata collection's hash
     348        if(!psHashAdd(mdTable, key, metadataItem)) {
     349            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
     350            return false;
     351        }
     352    }
     353
    311354    if(!psListAdd(mdList, location, metadataItem)) {
    312355        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
     
    363406METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_META_LOOKUPTABLE)
    364407METADATA_ADD_TYPE(Unknown,void*,PS_META_UNKNOWN)
     408METADATA_ADD_TYPE(Metadata,psMetadata*,PS_META_META)
    365409
    366410psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
  • trunk/psLib/src/types/psMetadata.h

    r3684 r3945  
    1111*  @author Ross Harman, MHPCC
    1212*
    13 *  @version $Revision: 1.44 $ $Name: not supported by cvs2svn $
    14 *  @date $Date: 2005-04-08 17:58:57 $
     13*  @version $Revision: 1.45 $ $Name: not supported by cvs2svn $
     14*  @date $Date: 2005-05-16 19:43:53 $
    1515*
    1616*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    5151    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
    5252    PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
    53     PS_META_MULTI                      ///< Used internally, do not create an metadata item of this type.
     53    PS_META_MULTI,                     ///< Used internally, do not create an metadata item of this type.
     54    PS_META_META                       ///< Metadata data (Stored as item.data.md).
    5455} psMetadataType;
    5556
     
    105106}
    106107psMetadataIterator;
    107 
    108108
    109109/** Metadata item data structure.
     
    316316psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
    317317                            const char* comment, psPtr value);
     318psBool psMetadataAddMetadata(psMetadata* md, psS32 location, const char* name,
     319                             const char* comment, psMetadata* value);
    318320
    319321/** Remove an item from metadata collection.
  • trunk/psLib/src/types/psMetadataConfig.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
  • trunk/psLib/src/types/psMetadataConfig.h

    r3381 r3945  
    1010 *  @author Robert DeSonia, MHPCC
    1111 *
    12  *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-03-07 20:58:50 $
     12 *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-05-16 19:43:53 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2121/// @{
    2222
     23typedef struct
     24{
     25    psArray*    nonUniqueKeyArray;
     26    psArray*    typeArray;
     27    psArray*    templateArray;
     28    psMetadata* metadata;
     29    char*       name;
     30}
     31p_psParseLevelInfo;
     32
     33p_psParseLevelInfo* p_psParseLevelInfoAlloc(void);
    2334
    2435/** Print metadata item to file.
  • trunk/psLib/src/xml/psXML.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
  • trunk/psLib/src/xml/psXML.h

    r3381 r3945  
    1010 *  @author Robert DeSonia, MHPCC
    1111 *
    12  *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-03-07 20:58:50 $
     12 *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-05-16 19:43:53 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2121/// @{
    2222
     23typedef struct
     24{
     25    psArray*    nonUniqueKeyArray;
     26    psArray*    typeArray;
     27    psArray*    templateArray;
     28    psMetadata* metadata;
     29    char*       name;
     30}
     31p_psParseLevelInfo;
     32
     33p_psParseLevelInfo* p_psParseLevelInfoAlloc(void);
    2334
    2435/** Print metadata item to file.
  • trunk/psLib/test/collections/tst_psMetadataIO.c

    r3779 r3945  
    44 *
    55 *  This test driver contains the following tests for psMetadata:
    6  *    Test A - Read config file with overwrite set true
    7  *    Test B - Read config file with overwrite set false
    8  *    Test C - Read config file without auto-allocation of metadata
    9  *    Test D - Attempt to use null fileName argument
    10  *    Test E - Attempt to open nonexistant file
    11  *    Test F - Free psMetadata
     6 *    Read config file with overwrite set true
     7 *    Read config file with overwrite set false
     8 *    Attempt to use null fileName argument
     9 *    Attempt to open nonexistant file
    1210 *
    1311 *  @author  Ross Harman, MHPCC
    1412 *  @author  Robert DeSonia, MHPCC
     13 *  @author  Eric Van Alst, MHPCC
    1514 *
    16  *  @version $Revision: 1.14 $  $Name: not supported by cvs2svn $
    17  *  @date  $Date: 2005-04-28 02:45:12 $
     15 *  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
     16 *  @date  $Date: 2005-05-16 19:41:40 $
    1817 *
    1918 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2524#include "psTest.h"
    2625
    27 static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
    28 static void printMetadata(psMetadata *metadata);
    29 static void printMetadataList(psList *metadataItemList, char* spaces);
    30 static void printMetadataTable(psHash *mdTable);
    31 
    32 static void printMetadata(psMetadata *metadata)
    33 {
    34     printf("Contents of metadata list:\n");
    35     printMetadataList(metadata->list, " ");
    36     printf("\nContents of metadata table:\n");
    37     printMetadataTable(metadata->table);
    38 }
    39 
    40 static void printMetadataList(psList *metadataItemList, char* spaces)
    41 {
    42     psMetadataItem *entryChild = NULL;
    43 
     26static psS32 testMetadataParseConfig(void);
     27static psS32 testMetadataParseConfig1(void);
     28static psS32 testMetadataParseConfig2(void);
     29
     30testDescription tests[] = {
     31                              {testMetadataParseConfig,000,"psMetadataParseConfig",0,false},
     32                              {testMetadataParseConfig1,000,"psMetadataParseConfig",0,false},
     33                              {testMetadataParseConfig2,000,"psMetadataParseConfig",0,false},
     34                              {NULL}
     35                          };
     36
     37static void writeMetadataItem(psMetadataItem* metadataIem, char* indentStr);
     38static void writeMetadata(psMetadata* metadata, char* indentStr);
     39static void writeMetadataList(psList *metadataItemList, char* indentStr);
     40
     41static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile);
     42static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile);
     43static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile);
     44static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile);
     45static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile);
     46
     47#define ERROR_TOL  0.0001
     48
     49const char testConfig3[] = "test3.config";
     50const psS32 testConfig3Fails = 1;
     51
     52const char testConfig2[] = "test2.config";
     53const psS32 testConfig2Fails = 17;
     54
     55// SDR-14 test config file #1
     56const char  testConfig1[] = "test1.config";
     57const psS32 testConfig1FailsOverwrite = 0;
     58const psS32 testConfig1Fails = 1;
     59const psS32 testConfig1Items = 25;
     60const char* testConfig1KeyOverwrite[] =
     61    {
     62        "Double","String","boolean","primes","comment",
     63        "comment","comment","comment","comment","Float",
     64        "boolean1","negprimes","vector1","vector2","vector3",
     65        "vector4","vector5","vector6","vector7","vector8",
     66        "CELL.00", "CELL.01","MYCELL","MYCELL","cell"
     67    };
     68const char* testConfig1CommentOverwrite[] =
     69    {
     70        "This is a comment","comment","The value of 'boolean' is 'true'","These are prime numbers",
     71        "","","","","",
     72        "This generates a warning, and, if 'overwrite' is 'false', is ignored","The value of 'boolean' is 'false'",
     73        "","","","","",
     74        "","","","",
     75        "","","","A number",""
     76    };
     77const psMetadataType testConfig1TypeOverwrite[] =
     78    {
     79        PS_META_F64, PS_META_STR, PS_META_BOOL, PS_META_VEC, PS_META_STR,
     80        PS_META_STR, PS_META_STR, PS_META_STR, PS_META_STR,  PS_META_F64,
     81        PS_META_BOOL, PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC,
     82        PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC,
     83        PS_META_META, PS_META_META, PS_META_META, PS_META_S32, PS_META_META
     84    };
     85const psS32 testConfig1ValueS32Overwrite[] =
     86    {
     87        0, 0, 0, 0, 0,
     88        0, 0, 0, 0, 0,
     89        0, 0, 0, 0, 0,
     90        0, 0, 0, 0, 0,
     91        0, 0, 0, 123, 0
     92    };
     93const psF32 testConfig1ValueF32Overwrite[] =
     94    {
     95        0.0, 0.0, 0.0, 0.0, 0.0,
     96        0.0, 0.0, 0.0, 0.0, 0.0,
     97        0.0, 0.0, 0.0, 0.0, 0.0,
     98        0.0, 0.0, 0.0, 0.0, 0.0,
     99        0.0, 0.0, 0.0, 0.0, 0.0
     100    };
     101const psF64 testConfig1ValueF64Overwrite[] =
     102    {
     103        1.23456789, 0.0, 0.0, 0.0, 0.0,
     104        0.0, 0.0, 0.0, 0.0, 1.23456,
     105        0.0, 0.0, 0.0, 0.0, 0.0,
     106        0.0, 0.0, 0.0, 0.0, 0.0,
     107        0.0, 0.0, 0.0, 0.0, 0.0
     108    };
     109const psBool testConfig1ValueBoolOverwrite[] =
     110    {
     111        false, false, true, false, false,
     112        false, false, false, false, false,
     113        false, false, false, false, false,
     114        false, false, false, false, false,
     115        false, false, false, false, false
     116    };
     117const char* testConfig1ValueStrOverwrite[] =
     118    {
     119        "", "This is the string that forms the value","","","This",
     120        "is","a","non-unique","key","",
     121        "","","","","",
     122        "","","","","",
     123        "","","","",""
     124    };
     125const psS32 testConfig1ValueVecItemsU8 = 7;
     126const psElemType testConfig1ValueVecTypeU8 = PS_TYPE_U8;
     127const psU8 testConfig1ValueVecValueU8[] =
     128    {
     129        2, 3, 5, 7, 11, 13, 17
     130    };
     131const psS32 testConfig1ValueVecItemsS8 = 8;
     132const psElemType testConfig1ValueVecTypeS8 = PS_TYPE_S8;
     133const psS8 testConfig1ValueVecValueS8[] =
     134    {
     135        -2, -3, -5, -7, -11, -13, -17, -19
     136    };
     137const psS32 testConfig1ValueVecItemsU16 = 5;
     138const psElemType testConfig1ValueVecTypeU16 = PS_TYPE_U16;
     139const psU16 testConfig1ValueVecValueU16[] =
     140    {
     141        0, 1, 2, 4, 8
     142    };
     143const psS32 testConfig1ValueVecItemsU32 = 6;
     144const psElemType testConfig1ValueVecTypeU32 = PS_TYPE_U32;
     145const psU32 testConfig1ValueVecValueU32[] =
     146    {
     147        0, 8, 16, 32, 64, 128
     148    };
     149const psS32 testConfig1ValueVecItemsU64 = 3;
     150const psElemType testConfig1ValueVecTypeU64 = PS_TYPE_U64;
     151const psU64 testConfig1ValueVecValueU64[] =
     152    {
     153        0, 64, 256
     154    };
     155const psS32 testConfig1ValueVecItemsS16 = 5;
     156const psElemType testConfig1ValueVecTypeS16 = PS_TYPE_S16;
     157const psS16 testConfig1ValueVecValueS16[] =
     158    {
     159        -2, -1, 0, 1, 2
     160    };
     161const psS32 testConfig1ValueVecItemsS32 = 6;
     162const psElemType testConfig1ValueVecTypeS32 = PS_TYPE_S32;
     163const psS32 testConfig1ValueVecValueS32[] =
     164    {
     165        -4, -2, 0, 2, 4, 6
     166    };
     167const psS32 testConfig1ValueVecItemsS64 = 7;
     168const psElemType testConfig1ValueVecTypeS64 = PS_TYPE_S64;
     169const psS64 testConfig1ValueVecValueS64[] =
     170    {
     171        -16, -4, 0, 4, 16, 36, 64
     172    };
     173const psS32 testConfig1ValueVecItemsF32 = 4;
     174const psElemType testConfig1ValueVecTypeF32 = PS_TYPE_F32;
     175const psF32 testConfig1ValueVecValueF32[] =
     176    {
     177        -1.03, 1.04, -1.05, 1.06
     178    };
     179const psS32 testConfig1ValueVecItemsF64 = 5;
     180const psElemType testConfig1ValueVecTypeF64 = PS_TYPE_F64;
     181const psF64 testConfig1ValueVecValueF64[] =
     182    {
     183        -2.22, 2.21, -2.20, 2.19, -2.18
     184    };
     185const psS32 testConfig1ValueMetaItems1 = 3;
     186const char* testConfig1ValueMetaNames1[] =
     187    {
     188        "EXTNAME","BIASSEC","CHIP"
     189    };
     190const psMetadataType testConfig1ValueMetaTypes1[] =
     191    {
     192        PS_META_STR, PS_META_STR, PS_META_STR
     193    };
     194const char* testConfig1ValueMetaValue1[] =
     195    {
     196        "CCD00","BSEC-00","CHIP.00"
     197    };
     198const psS32 testConfig1ValueMetaItems2 = 3;
     199const char* testConfig1ValueMetaNames2[] =
     200    {
     201        "EXTNAME","BIASSEC","CHIP"
     202    };
     203const psMetadataType testConfig1ValueMetaTypes2[] =
     204    {
     205        PS_META_STR, PS_META_STR, PS_META_STR
     206    };
     207const char* testConfig1ValueMetaValue2[] =
     208    {
     209        "CCD01","BSEC-01","CHIP.00"
     210    };
     211const psS32 testConfig1ValueMetaItems3 = 4;
     212const char* testConfig1ValueMetaNames3[] =
     213    {
     214        "EXTNAME","BIASSEC","CHIP","NCELL"
     215    };
     216const psMetadataType testConfig1ValueMetaTypes3[] =
     217    {
     218        PS_META_STR, PS_META_STR, PS_META_STR, PS_META_S32
     219    };
     220const char* testConfig1ValueMetaValueStr3[] =
     221    {
     222        "CCD00","BSEC-00","CHIP.00",""
     223    };
     224const psS32 testConfig1ValueMetaValueS323[] =
     225    {
     226        0, 0, 0, 24
     227    };
     228
     229static void writeMetadata(psMetadata* metadata, char* indentStr)
     230{
     231    writeMetadataList(metadata->list, indentStr);
     232}
     233
     234static void writeMetadataList(psList* metadataItemList, char* indentStr)
     235{
     236    psMetadataItem* entryChild        = NULL;
     237    psMetadataItem* searchChild       = NULL;
     238    psArray*        nonUniqueKeyArray = NULL;
     239    psBool          keyFound          = false;
     240    char*           tempKey           = NULL;
     241
     242    // Allocate iterator for moving through metadata list
    44243    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
    45 
    46     while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
    47         printMetadataItem(entryChild, spaces);
     244    psListIterator* searchIter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
     245
     246    // Allocate array for nonUnique key names
     247    nonUniqueKeyArray = psArrayAlloc(10);
     248    nonUniqueKeyArray->n = 0;
     249
     250
     251    // Loop through all items in the list
     252    while ( (entryChild = psListGetAndIncrement(iter)) != NULL) {
     253        // Search list for another entry with same key name
     254        // Check if last entry
     255        if(iter->index != metadataItemList->size) {
     256            // Set search iterator to index
     257            if(!psListIteratorSet(searchIter,iter->index) ) {
     258                psError(PS_ERR_UNKNOWN,true,"Error searching list for multiple keys");
     259                break;
     260            }
     261            keyFound = false;
     262            while ( (searchChild = psListGetAndIncrement(searchIter)) != NULL) {
     263                if(strcmp(entryChild->name,searchChild->name) == 0) {
     264                    // Search nonUnique key array
     265                    for(psS32 i = 0; i < nonUniqueKeyArray->n; i++) {
     266                        if(strcmp(entryChild->name,nonUniqueKeyArray->data[i]) == 0) {
     267                            keyFound = true;
     268                        }
     269                    }
     270                    if(!keyFound) {
     271                        // Add key to non-unique array
     272                        tempKey = psStringCopy(entryChild->name);
     273                        nonUniqueKeyArray = psArrayAdd(nonUniqueKeyArray,1,tempKey);
     274                        psFree(tempKey);
     275
     276                        // Print MULTI line
     277                        printf("%-25s MULTI\n",entryChild->name);
     278
     279                        // Break out of loop
     280                        break;
     281                    }
     282                }
     283            }
     284        }
     285        writeMetadataItem(entryChild,indentStr);
    48286    }
    49287
    50288    psFree(iter);
    51 }
    52 
    53 static void printMetadataTable(psHash *mdTable)
    54 {
    55     psS32 i;
    56     psHashBucket* ptr = NULL;
    57     for(i=0; i<mdTable->nbucket; i++) {
    58         ptr = mdTable->buckets[i];
    59         while (ptr != NULL) {
    60             printMetadataItem(ptr->data, " ");
    61             ptr = ptr->next;
    62         }
    63     }
    64 }
    65 
    66 static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
    67 {
    68     char* vecStr;
    69 
    70     printf("%sKey Name: %8s  ", spaces, metadataItem->name);
    71     printf("Key mdType: 0x%08x ", metadataItem->type);
    72 
    73     switch (metadataItem->type) {
    74     case PS_META_MULTI:
    75         printf("Key Value: %17c", ' ');
     289    psFree(searchIter);
     290    psFree(nonUniqueKeyArray);
     291}
     292
     293char* vectorToConfigString(psVector* vector)
     294{
     295    psS32  maxLength = 256;
     296
     297    char* str = psAlloc(sizeof(char)*maxLength+1);
     298
     299    if (vector == NULL) {
     300        snprintf(str,maxLength, "NULL");
     301        return str;
     302    }
     303
     304    int size = vector->n;
     305
     306    if (size == 0) {
     307        snprintf(str,maxLength, " ");
     308        return str;
     309    }
     310
     311    char* tempStr = psAlloc(sizeof(char)*maxLength+1);
     312    *str = '\0';
     313    bool full = false;
     314
     315    #define APPEND_ELEMENTS_CASE(TYPE, NATIVE_TYPE, FORMAT) \
     316case PS_TYPE_##TYPE: \
     317    strcat(str,#TYPE); \
     318    for(psS32 i = 0; i < (strlen(str)-6); i++) {  \
     319        strcat(str," "); \
     320    } \
     321    for (lcv=0; lcv < size && ! full; lcv++) { \
     322        snprintf(tempStr, maxLength, "%s" FORMAT, prefix, (NATIVE_TYPE) (vector->data.TYPE[lcv])); \
     323        strncat(str,tempStr,maxLength); \
     324        full = (strlen(str) > maxLength-2); \
     325        prefix = ","; \
     326    } \
     327    break;
     328
     329    int lcv;
     330    char* prefix = " ";
     331    switch(vector->type.type) {
     332        APPEND_ELEMENTS_CASE(S8,char,"%hd")
     333        APPEND_ELEMENTS_CASE(S16,short int,"%hd")
     334        APPEND_ELEMENTS_CASE(S32,int,"%d")
     335        APPEND_ELEMENTS_CASE(S64,long,"%ld")
     336        APPEND_ELEMENTS_CASE(U8,unsigned char,"%hu")
     337        APPEND_ELEMENTS_CASE(U16,unsigned short,"%hu")
     338        APPEND_ELEMENTS_CASE(U32,unsigned int, "%u")
     339        APPEND_ELEMENTS_CASE(U64,unsigned long,"%lu")
     340        APPEND_ELEMENTS_CASE(F32,double,"%g")
     341        APPEND_ELEMENTS_CASE(F64,double,"%g")
     342    default:
     343        snprintf(str,maxLength,"INVALID TYPE");
    76344        break;
     345    }
     346
     347    psFree(tempStr);
     348
     349    return str;
     350}
     351
     352
     353static void writeMetadataItem(psMetadataItem *metadataItem, char* indentStr)
     354{
     355    char*  vecStr;
     356
     357    switch(metadataItem->type) {
    77358    case PS_META_BOOL:
    78         printf("Key Value: %15d  ", metadataItem->data.B);
     359        printf("%s%-25s BOOL  %40d",indentStr,metadataItem->name,metadataItem->data.B);
    79360        break;
    80361    case PS_META_S32:
    81         printf("Key Value: %15d  ", metadataItem->data.S32);
     362        printf("%s%-25s S32   %40d",indentStr,metadataItem->name,metadataItem->data.S32);
    82363        break;
    83364    case PS_META_F32:
    84         printf("Key Value: %15.3f  ", metadataItem->data.F32);
     365        printf("%s%-25s F32   %40f",indentStr,metadataItem->name,metadataItem->data.F32);
    85366        break;
    86367    case PS_META_F64:
    87         printf("Key Value: %15.3f  ", metadataItem->data.F64);
     368        printf("%s%-25s F64   %40lf",indentStr,metadataItem->name,metadataItem->data.F64);
    88369        break;
    89370    case PS_META_VEC:
    90         vecStr = (char*)psVectorToString((psVector*)metadataItem->data.V, 15);
    91         printf("Key Value: %15s  ", vecStr);
     371        vecStr = (char*)vectorToConfigString((psVector*)metadataItem->data.V);
     372        printf("%s@%-24s %s",indentStr,metadataItem->name,vecStr);
    92373        psFree(vecStr);
    93374        break;
    94375    case PS_META_STR:
    95         printf("Key Value: %15s  ", (char*)metadataItem->data.V);
     376        printf("%s%-25s STR   %40s",indentStr,metadataItem->name,(char*)metadataItem->data.V);
     377        break;
     378    case PS_META_META:
     379        printf("%s%-25s METADATA\n",indentStr,metadataItem->name);
     380        writeMetadata((psMetadata*)metadataItem->data.md,"    ");
    96381        break;
    97382    default:
    98         printf("Bad type: 0x%08x ", metadataItem->type);
    99     }
    100     printf("Key Comment: %s\n", metadataItem->comment);
    101 
    102     if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
    103         printMetadataList(metadataItem->data.V, "    ");
    104     }
    105 }
    106 
     383        printf("#%s%-24s BAD TYPE=%d",indentStr,metadataItem->name,metadataItem->type);
     384        break;
     385    }
     386    if(strlen(metadataItem->comment) > 0) {
     387        printf("  # %-20s\n",metadataItem->comment);
     388    } else {
     389        printf("\n");
     390    }
     391}
     392
     393static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile)
     394{
     395    psBool     returnValue = true;
     396
     397    // Verify the expected number of failed lines
     398    if(failedLines != expectedFailedLines) {
     399        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of failed lines = %d not as expected %d",
     400                configFile,failedLines,expectedFailedLines);
     401        returnValue = false;
     402    }
     403    return returnValue;
     404}
     405
     406static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile)
     407{
     408    psBool     returnValue = true;
     409
     410    // Verify the number of items in metadata
     411    if(md->list->size != expectedItems) {
     412        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of items = %d not as expected %d",
     413                configFile,md->list->size, expectedItems);
     414        returnValue = false;
     415    }
     416    return returnValue;
     417}
     418
     419static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile)
     420{
     421    psBool    returnValue = true;
     422
     423    // Compare key names
     424    if(strcmp(mdItem->name,expectedName) != 0) {
     425        psError(PS_ERR_UNKNOWN,true,"File: %s : Key name %s not as expected %s",
     426                configFile,mdItem->name,expectedName);
     427        returnValue = false;
     428    }
     429
     430    return returnValue;
     431}
     432
     433static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile)
     434{
     435    psBool     returnValue = true;
     436
     437    // Compare types
     438    if(mdItem->type != expectedType) {
     439        psError(PS_ERR_UNKNOWN,true,"File: %s : Type %d not as expected %d",
     440                configFile,mdItem->type,expectedType);
     441        returnValue = false;
     442    }
     443    return returnValue;
     444}
     445
     446static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile)
     447{
     448    psBool    returnValue = true;
     449
     450    // Compare comments
     451    if(strcmp(mdItem->comment,expectedComment) != 0) {
     452        psError(PS_ERR_UNKNOWN,true,"File: %s : Comment %s not as expected %s",
     453                configFile,mdItem->comment,expectedComment);
     454        returnValue = false;
     455    }
     456    return returnValue;
     457}
    107458
    108459psS32 main(psS32 argc, char* argv[])
    109460{
    110     // Test A - Read config file with overwrite set true
    111     printPositiveTestHeader(stdout, "psMetadata", "Test A - Read config file with overwrite set true");
    112     psMetadata *metadata1 = NULL;
    113     psU32 failedLines1 = 0;
    114     metadata1 = psMetadataParseConfig(metadata1, &failedLines1, "test.config", true);
    115     printf("Failed lines: %d Expected: 6\n", failedLines1);
    116     printMetadata(metadata1);
    117     printFooter(stdout, "psMetadata", "Test A - Read config file with overwrite set true", true);
    118 
    119 
    120     // Test B - Read config file with overwrite set false
    121     printPositiveTestHeader(stdout, "psMetadata", "Test B - Read config file with overwrite set false");
    122     psMetadata *metadata2 = NULL;
    123     psU32 failedLines2 = 0;
    124     metadata2 = psMetadataParseConfig(metadata2, &failedLines2, "test.config", false);
    125     printf("Failed lines: %d Expected: 7 ", failedLines2);
    126     printMetadata(metadata2);
    127     printFooter(stdout, "psMetadata", "Test B - Read config file with overwrite set false", true);
    128 
    129 
    130     // Test C - Read config file without auto-allocation of metadata
    131     printPositiveTestHeader(stdout, "psMetadata", "Test C - Read config file without auto-allocation of metadata");
    132     psMetadata *metadata3 = psMetadataAlloc();
    133     psU32 failedLines3 = 0;
    134     metadata3 = psMetadataParseConfig(metadata3, &failedLines3, "test.config", true);
    135     printf("Failed lines: %d Expected: 6 ", failedLines3);
    136     printMetadata(metadata3);
    137     printFooter(stdout, "psMetadata", "Test C - Read config file without auto-allocation of metadata", true);
    138 
    139 
    140     // Test D - Attempt to use null fileName argument
    141     printNegativeTestHeader(stdout,"psMetadataIO", "Test D - Attempt to use null fileName argument",
    142                             "Null failedLines not allowed", 0);
    143     psMetadataParseConfig(metadata1, &failedLines1, NULL, true);
    144     printFooter(stdout, "psMetadata", "Test D - Attempt to use null fileName argument", true);
    145 
    146 
    147     // Test E - Attempt to open nonexistant file
    148     printNegativeTestHeader(stdout,"psMetadataIO", "Test E - Attempt to open nonexistant file",
    149                             "Error opening file", 0);
    150     psMetadataParseConfig(metadata1, &failedLines1, "abcedfg", true);
    151     printFooter(stdout, "psMetadata", "Test E - Attempt to open nonexistant file", true);
    152 
    153 
    154     // Test F - Free psMetadata
    155     printPositiveTestHeader(stdout, "psMetadata", "Test F - Free psMetadata");
     461    psLogSetLevel(PS_LOG_INFO);
     462
     463    if( !runTestSuite(stderr,"psMetadataParseConfig",tests,argc,argv)) {
     464        return 1;
     465    }
     466
     467    return 0;
     468}
     469
     470psS32 testMetadataParseConfig(void)
     471{
     472    psMetadata*       metadata1      = NULL;
     473    psMetadataItem*   entryChild     = NULL;
     474    psS32             failedLines    = 0;
     475    psListIterator*   iter           = NULL;
     476    psListIterator*   mdIter         = NULL;
     477    psMetadataItem*   mdChild        = NULL;
     478    psS32             metaCounter    = 0;
     479    psS32             mdCounter      = 0;
     480
     481    // Read config file test1.config with overwrite set true
     482    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig1,true);
     483    // Verify the expected number of failed lines
     484    if(!checkFailedLines(failedLines,testConfig1FailsOverwrite,(char*)testConfig1)) {
     485        return 1;
     486    }
     487    // Verify the number of items in metadata
     488    if(!checkNumberOfItems(metadata1,testConfig1Items,(char*)testConfig1)) {
     489        return 2;
     490    }
     491    // Verify metadata item quads
     492    iter = psListIteratorAlloc(metadata1->list, PS_LIST_HEAD, true);
     493    for(psS32 i = 0; i < testConfig1Items; i++) {
     494        // Get list item
     495        entryChild = psListGetAndIncrement(iter);
     496
     497        // Verify end of list not reached prematurely
     498        if(entryChild == NULL) {
     499            psError(PS_ERR_UNKNOWN,true,"End of list encountered at %d not as expected %d",
     500                    i,testConfig1Items);
     501            return i*10+1;
     502        }
     503        // Verify name
     504        if(!checkItemName(entryChild,(char*)testConfig1KeyOverwrite[i],(char*)testConfig1)) {
     505            return i*10+2;
     506        }
     507        // Verify type
     508        if(!checkItemType(entryChild,testConfig1TypeOverwrite[i],(char*)testConfig1)) {
     509            return i*10+3;
     510        }
     511        // Verify comment
     512        if(!checkItemComment(entryChild,(char*)testConfig1CommentOverwrite[i],(char*)testConfig1)) {
     513            return i*10+4;
     514        }
     515        // Compare values
     516        switch(entryChild->type) {
     517        case PS_META_S32:
     518            if(entryChild->data.S32 != testConfig1ValueS32Overwrite[i]) {
     519                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
     520                        testConfig1,entryChild->data.S32, testConfig1ValueS32Overwrite[i]);
     521                return i*10+5;
     522            }
     523            break;
     524        case PS_META_F32:
     525            if(fabs(entryChild->data.F32 - testConfig1ValueF32Overwrite[i]) > ERROR_TOL) {
     526                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %f not as expected %f",
     527                        testConfig1,entryChild->data.F32, testConfig1ValueF32Overwrite[i]);
     528                return i*10+5;
     529            }
     530            break;
     531        case PS_META_F64:
     532            if(fabs(entryChild->data.F64 - testConfig1ValueF64Overwrite[i]) > ERROR_TOL) {
     533                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %lf not as expected %lf",
     534                        testConfig1,entryChild->data.F64, testConfig1ValueF64Overwrite[i]);
     535                return i*10+5;
     536            }
     537            break;
     538        case PS_META_BOOL:
     539            if(entryChild->data.B != testConfig1ValueBoolOverwrite[i]) {
     540                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
     541                        testConfig1,entryChild->data.B,testConfig1ValueBoolOverwrite[i]);
     542                return i*10+5;
     543            }
     544            break;
     545        case PS_META_STR:
     546            if(strcmp(entryChild->data.V,testConfig1ValueStrOverwrite[i]) != 0) {
     547                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %s not as expected %s",
     548                        testConfig1,entryChild->data.V,testConfig1ValueStrOverwrite[i]);
     549                return i*10+5;
     550            }
     551            break;
     552        case PS_META_VEC:
     553            // Verify the correct number of entries
     554            switch(((psVector*)(entryChild->data.V))->type.type) {
     555            case PS_TYPE_U8:
     556                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU8) {
     557                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     558                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU8);
     559                    return i*10+5;
     560                }
     561                // Verify the correct type
     562                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU8) {
     563                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     564                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU8);
     565                    return i*10+5;
     566                }
     567                // Verify the values in vector
     568                for(psS32 j = 0; j < testConfig1ValueVecItemsU8; j++) {
     569                    if(((psVector*)entryChild->data.V)->data.U8[j] != testConfig1ValueVecValueU8[j]) {
     570                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     571                                testConfig1,j,((psVector*)entryChild->data.V)->data.U8[j],
     572                                testConfig1ValueVecValueU8[j]);
     573                        return i*10+5*j;
     574                    }
     575                }
     576                break;
     577            case PS_TYPE_U16:
     578                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU16) {
     579                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     580                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU16);
     581                    return i*10+5;
     582                }
     583                // Verify the correct type
     584                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU16) {
     585                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     586                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU16);
     587                    return i*10+5;
     588                }
     589                // Verify the values in vector
     590                for(psS32 j = 0; j < testConfig1ValueVecItemsU16; j++) {
     591                    if(((psVector*)entryChild->data.V)->data.U16[j] != testConfig1ValueVecValueU16[j]) {
     592                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     593                                testConfig1,j,((psVector*)entryChild->data.V)->data.U16[j],
     594                                testConfig1ValueVecValueU16[j]);
     595                        return i*10+5*j;
     596                    }
     597                }
     598                break;
     599            case PS_TYPE_U32:
     600                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU32) {
     601                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     602                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU32);
     603                    return i*10+5;
     604                }
     605                // Verify the correct type
     606                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU32) {
     607                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     608                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU32);
     609                    return i*10+5;
     610                }
     611                // Verify the values in vector
     612                for(psS32 j = 0; j < testConfig1ValueVecItemsU32; j++) {
     613                    if(((psVector*)entryChild->data.V)->data.U32[j] != testConfig1ValueVecValueU32[j]) {
     614                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     615                                testConfig1,j,((psVector*)entryChild->data.V)->data.U32[j],
     616                                testConfig1ValueVecValueU32[j]);
     617                        return i*10+5*j;
     618                    }
     619                }
     620                break;
     621            case PS_TYPE_U64:
     622                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU64) {
     623                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     624                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU64);
     625                    return i*10+5;
     626                }
     627                // Verify the correct type
     628                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU64) {
     629                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     630                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU64);
     631                    return i*10+5;
     632                }
     633                // Verify the values in vector
     634                for(psS32 j = 0; j < testConfig1ValueVecItemsU64; j++) {
     635                    if(((psVector*)entryChild->data.V)->data.U64[j] != testConfig1ValueVecValueU64[j]) {
     636                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
     637                                testConfig1,j,((psVector*)entryChild->data.V)->data.U64[j],
     638                                testConfig1ValueVecValueU64[j]);
     639                        return i*10+5*j;
     640                    }
     641                }
     642                break;
     643            case PS_TYPE_S8:
     644                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS8) {
     645                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     646                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS8);
     647                    return i*10+5;
     648                }
     649                // Verify the correct type
     650                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS8) {
     651                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     652                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS8);
     653                    return i*10+5;
     654                }
     655                // Verify the values in vector
     656                for(psS32 j = 0; j < testConfig1ValueVecItemsS8; j++) {
     657                    if(((psVector*)entryChild->data.V)->data.S8[j] != testConfig1ValueVecValueS8[j]) {
     658                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     659                                testConfig1,j,((psVector*)entryChild->data.V)->data.S8[j],
     660                                testConfig1ValueVecValueS8[j]);
     661                        return i*10+5*j;
     662                    }
     663                }
     664                break;
     665            case PS_TYPE_S16:
     666                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS16) {
     667                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     668                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS16);
     669                    return i*10+5;
     670                }
     671                // Verify the correct type
     672                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS16) {
     673                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     674                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS16);
     675                    return i*10+5;
     676                }
     677                // Verify the values in vector
     678                for(psS32 j = 0; j < testConfig1ValueVecItemsS16; j++) {
     679                    if(((psVector*)entryChild->data.V)->data.S16[j] != testConfig1ValueVecValueS16[j]) {
     680                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     681                                testConfig1,j,((psVector*)entryChild->data.V)->data.S16[j],
     682                                testConfig1ValueVecValueS16[j]);
     683                        return i*10+5*j;
     684                    }
     685                }
     686                break;
     687            case PS_TYPE_S32:
     688                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS32) {
     689                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     690                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS32);
     691                    return i*10+5;
     692                }
     693                // Verify the correct type
     694                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS32) {
     695                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     696                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS32);
     697                    return i*10+5;
     698                }
     699                // Verify the values in vector
     700                for(psS32 j = 0; j < testConfig1ValueVecItemsS32; j++) {
     701                    if(((psVector*)entryChild->data.V)->data.S32[j] != testConfig1ValueVecValueS32[j]) {
     702                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
     703                                testConfig1,j,((psVector*)entryChild->data.V)->data.S32[j],
     704                                testConfig1ValueVecValueS32[j]);
     705                        return i*10+5*j;
     706                    }
     707                }
     708                break;
     709            case PS_TYPE_S64:
     710                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS64) {
     711                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     712                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS64);
     713                    return i*10+5;
     714                }
     715                // Verify the correct type
     716                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS64) {
     717                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     718                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS64);
     719                    return i*10+5;
     720                }
     721                // Verify the values in vector
     722                for(psS32 j = 0; j < testConfig1ValueVecItemsS64; j++) {
     723                    if(((psVector*)entryChild->data.V)->data.S64[j] != testConfig1ValueVecValueS64[j]) {
     724                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
     725                                testConfig1,j,((psVector*)entryChild->data.V)->data.S64[j],
     726                                testConfig1ValueVecValueS64[j]);
     727                        return i*10+5*j;
     728                    }
     729                }
     730                break;
     731            case PS_TYPE_F32:
     732                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF32) {
     733                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     734                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF32);
     735                    return i*10+5;
     736                }
     737                // Verify the correct type
     738                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF32) {
     739                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     740                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF32);
     741                    return i*10+5;
     742                }
     743                // Verify the values in vector
     744                for(psS32 j = 0; j < testConfig1ValueVecItemsF32; j++) {
     745                    if(fabs(((psVector*)entryChild->data.V)->data.F32[j]-testConfig1ValueVecValueF32[j])
     746                            > ERROR_TOL) {
     747                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %f not as expected %f",
     748                                testConfig1,j,((psVector*)entryChild->data.V)->data.F32[j],
     749                                testConfig1ValueVecValueF32[j]);
     750                        return i*10+5*j;
     751                    }
     752                }
     753                break;
     754            case PS_TYPE_F64:
     755                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF64) {
     756                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
     757                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF64);
     758                    return i*10+5;
     759                }
     760                // Verify the correct type
     761                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF64) {
     762                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
     763                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF64);
     764                    return i*10+5;
     765                }
     766                // Verify the values in vector
     767                for(psS32 j = 0; j < testConfig1ValueVecItemsF64; j++) {
     768                    if(fabs(((psVector*)entryChild->data.V)->data.F64[j]-testConfig1ValueVecValueF64[j])
     769                            > ERROR_TOL) {
     770                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %lf not as expected %lf",
     771                                testConfig1,j,((psVector*)entryChild->data.V)->data.F64[j],
     772                                testConfig1ValueVecValueF64[j]);
     773                        return i*10+5*j;
     774                    }
     775                }
     776                break;
     777            default:
     778                break;
     779            }
     780            break;
     781        case PS_META_META:
     782            if(metaCounter == 0) {
     783                // Check if number of items is as expected
     784                if(entryChild->data.md->list->size != testConfig1ValueMetaItems1) {
     785                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 items %d not as expected %d",
     786                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems1);
     787                    return i*10+6;
     788                }
     789                // Loop through metadata items
     790                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
     791                mdCounter = 0;
     792                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
     793                    if(strcmp(mdChild->name,testConfig1ValueMetaNames1[mdCounter]) != 0) {
     794                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 name[%d] %s not as expected %s",
     795                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames1[mdCounter]);
     796                        return i*10+6*mdCounter;
     797                    }
     798                    if(mdChild->type != testConfig1ValueMetaTypes1[mdCounter]) {
     799                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 type[%d] %d not as expected %d",
     800                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes1[mdCounter]);
     801                        return i*10+6*mdCounter;
     802                    }
     803                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]) != 0) {
     804                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 value[%d] %s not as expected %s",
     805                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]);
     806                        return i*10+6*mdCounter;
     807                    }
     808                    mdCounter++;
     809                }
     810                psFree(mdIter);
     811            } else if(metaCounter == 1) {
     812                // Check if number of items is as expected
     813                if(entryChild->data.md->list->size != testConfig1ValueMetaItems2) {
     814                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 items %d not as expected %d",
     815                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems2);
     816                    return i*10+6;
     817                }
     818                // Loop through metadata items
     819                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
     820                mdCounter = 0;
     821                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
     822                    if(strcmp(mdChild->name,testConfig1ValueMetaNames2[mdCounter]) != 0) {
     823                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 name[%d] %s not as expected %s",
     824                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames2[mdCounter]);
     825                        return i*10+6*mdCounter;
     826                    }
     827                    if(mdChild->type != testConfig1ValueMetaTypes2[mdCounter]) {
     828                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 type[%d] %d not as expected %d",
     829                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes2[mdCounter]);
     830                        return i*10+6*mdCounter;
     831                    }
     832                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]) != 0) {
     833                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 value[%d] %s not as expected %s",
     834                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]);
     835                        return i*10+6*mdCounter;
     836                    }
     837                    mdCounter++;
     838                }
     839                psFree(mdIter);
     840            } else if(metaCounter == 2) {
     841                // Check if number of items is as expected
     842                if(entryChild->data.md->list->size != testConfig1ValueMetaItems3) {
     843                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 items %d not as expected %d",
     844                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems3);
     845                    return i*10+6;
     846                }
     847                // Loop through metadata items
     848                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
     849                mdCounter = 0;
     850                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
     851                    if(strcmp(mdChild->name,testConfig1ValueMetaNames3[mdCounter]) != 0) {
     852                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 name[%d] %s not as expected %s",
     853                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames3[mdCounter]);
     854                        return i*10+6*mdCounter;
     855                    }
     856                    if(mdChild->type != testConfig1ValueMetaTypes3[mdCounter]) {
     857                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 type[%d] %d not as expected %d",
     858                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes3[mdCounter]);
     859                        return i*10+6*mdCounter;
     860                    }
     861                    switch(mdChild->type) {
     862                    case PS_META_STR:
     863                        if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValueStr3[mdCounter]) != 0) {
     864                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %s not as expected %s",
     865                                    testConfig1,mdCounter,(char*)mdChild->data.V,
     866                                    testConfig1ValueMetaValueStr3[mdCounter]);
     867                            return i*10+6*mdCounter;
     868                        }
     869                        break;
     870                    case PS_META_S32:
     871                        if(mdChild->data.S32 != testConfig1ValueMetaValueS323[mdCounter]) {
     872                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %d not as expected %d",
     873                                    testConfig1,mdCounter,mdChild->data.S32,
     874                                    testConfig1ValueMetaValueS323[mdCounter]);
     875                            return i*10+6*mdCounter;
     876                        }
     877                        break;
     878                    default:
     879                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] unknown type",
     880                                testConfig1,mdCounter);
     881                        return i*10+6*mdCounter;
     882                        break;
     883                    }
     884                    mdCounter++;
     885                }
     886                psFree(mdIter);
     887            }
     888            metaCounter++;
     889            break;
     890        default:
     891            psError(PS_ERR_UNKNOWN,true,"Unexpected type %d encountered",entryChild->type);
     892            return i*10+5;
     893            break;
     894        }
     895    }
     896
     897    writeMetadata(metadata1,"");
     898
    156899    psFree(metadata1);
    157     psFree(metadata2);
    158     psFree(metadata3);
    159     if(psMemCheckLeaks(0, NULL, stdout,false)) {
    160         psError(PS_ERR_UNKNOWN,true,"Memory leak detected");
    161         return 10;
    162     }
    163     psMemCheckCorruption(0);
    164     psS32 nBad = psMemCheckCorruption(0);
    165     if(nBad) {
    166         printf("ERROR: Found %d bad memory blocks\n", nBad);
    167     }
    168     printFooter(stdout, "psMetadata", "Test F - Free psMetadata", true);
    169 
    170900
    171901    return 0;
    172902}
     903
     904psS32 testMetadataParseConfig1(void)
     905{
     906    psMetadata*       metadata1      = NULL;
     907    psS32             failedLines    = 0;
     908
     909    // Read config file test2.config with overwrite set true
     910    // This file contains parse errors
     911    psLogMsg(__func__,PS_LOG_INFO,"Following should generate parse error message");
     912    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig2,true);
     913    // Verify the expected number of failed lines
     914    if(!checkFailedLines(failedLines,testConfig2Fails,(char*)testConfig2)) {
     915        return 1;
     916    }
     917    // Verify return value is null
     918    if(metadata1 != NULL) {
     919        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for failed parse");
     920        return 2;
     921    }
     922
     923    // Attempt parse a non-existant file
     924    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
     925    metadata1 = psMetadataParseConfig(metadata1,&failedLines,"ab.config",true);
     926    if(metadata1 != NULL) {
     927        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for non-existant file");
     928        return 3;
     929    }
     930
     931    // Attempt parse with NULL failed lines ptr
     932    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL failed lines arg");
     933    metadata1 = psMetadataParseConfig(metadata1,NULL,testConfig2,true);
     934    if(metadata1 != NULL) {
     935        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for NULL failed lines argument");
     936        return 4;
     937    }
     938
     939    // Attempt parse with NULL file name
     940    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL file name arg");
     941    metadata1 = psMetadataParseConfig(metadata1,&failedLines,NULL,true);
     942    if(metadata1 != NULL) {
     943        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for NULL filename argument");
     944        return 5;
     945    }
     946
     947    psFree(metadata1);
     948
     949    return 0;
     950}
     951
     952psS32 testMetadataParseConfig2(void)
     953{
     954    psMetadata*       metadata1      = NULL;
     955    psS32             failedLines    = 0;
     956
     957    // Read config file test1.config with overwrite set false
     958    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error of duplicate key names");
     959    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig3,false);
     960    // Verify the expected number of failed lines
     961    if(!checkFailedLines(failedLines,testConfig3Fails,(char*)testConfig3)) {
     962        return 1;
     963    }
     964    if(metadata1 != NULL) {
     965        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for failed due to overwrite false");
     966        return 2;
     967    }
     968    psFree(metadata1);
     969
     970    return 0;
     971}
     972
  • trunk/psLib/test/collections/verified/tst_psMetadataIO.stderr

    r3690 r3945  
     1/***************************** TESTPOINT ******************************************\
     2*             TestFile: tst_psMetadataIO.c                                         *
     3*            TestPoint: psMetadataParseConfig{psMetadataParseConfig}               *
     4*             TestType: Positive                                                   *
     5\**********************************************************************************/
     6
     7<DATE><TIME>|<HOST>|W|psMetadataAddItem
     8    Metadata item Float has been replaced
     9
     10---> TESTPOINT PASSED (psMetadataParseConfig{psMetadataParseConfig} | tst_psMetadataIO.c)
     11
     12/***************************** TESTPOINT ******************************************\
     13*             TestFile: tst_psMetadataIO.c                                         *
     14*            TestPoint: psMetadataParseConfig{psMetadataParseConfig}               *
     15*             TestType: Positive                                                   *
     16\**********************************************************************************/
     17
     18<DATE><TIME>|<HOST>|I|testMetadataParseConfig1
     19    Following should generate parse error message
     20<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     21    Failed to parse the value 'X' of metadata item boolean, type BOOL, on line 2 of test2.config.
     22<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     23    Failed to read a metadata value on line 4 of test2.config.
     24<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     25    Failed to read a metadata value on line 7 of test2.config.
     26<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     27    Failed to parse the value 'x,y,z' of metadata item @vector1, type U8, on line 8 of test2.config.
     28<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     29    Failed to read a metadata type on line 9 of test2.config.
     30<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     31    Failed to read a metadata value on line 9 of test2.config.
     32<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     33    Failed to parse the value '' of metadata item @vector3, type F8, on line 10 of test2.config.
     34<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     35    Duplicate MULTI specifier on line 14 of test2.config.
     36<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     37    Metadata type 'CELL', found on line 17 of test2.config, is not invalid.
     38<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     39    Failed to parse the value 'aabb' of metadata item value1, type F64, on line 20 of test2.config.
     40<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     41    Failed to parse the value 'ccdd' of metadata item value2, type S32, on line 21 of test2.config.
     42<DATE><TIME>|<HOST>|E|parseLine (FILE:LINENO)
     43    More than one '@' character not allowed.  Found on line 24 of test2.config.
     44<DATE><TIME>|<HOST>|E|parseLine (FILE:LINENO)
     45    Failed to read a metadata type on line 27 of test2.config.
     46<DATE><TIME>|<HOST>|E|parseLine (FILE:LINENO)
     47    Specified type, CELL, on line 31 of test2.config is already defined.
     48<DATE><TIME>|<HOST>|E|psMetadataAddItem (FILE:LINENO)
     49    Duplicate metadata item name is not allowed.  Use a psMetadataFlags option to allow such action.
     50<DATE><TIME>|<HOST>|E|parseLine (FILE:LINENO)
     51    Metadata type 'NEWCELL', found on line 37 of test2.config, is not invalid.
     52<DATE><TIME>|<HOST>|E|parseMetadataItem (FILE:LINENO)
     53    Failed to read a metadata OURCELL on line 40 of test2.config.
     54<DATE><TIME>|<HOST>|E|parseLine (FILE:LINENO)
     55    Metadata type 'NEWCELL1', found on line 43 of test2.config, is not invalid.
     56<DATE><TIME>|<HOST>|I|testMetadataParseConfig1
     57    Following should generate error message
    158<DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    2     Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
     59    Failed to open file 'ab.config'. Check if it exists and it has the proper permissions.
     60<DATE><TIME>|<HOST>|I|testMetadataParseConfig1
     61    Following should generate an error message for NULL failed lines arg
    362<DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    4     Failed to read a metadata value on line 95 of test.config.
     63    Unallowable operation: nFail is NULL.
     64<DATE><TIME>|<HOST>|I|testMetadataParseConfig1
     65    Following should generate an error message for NULL file name arg
    566<DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    6     Metadata type '99.999', found on line 101 of test.config, is not invalid.
    7 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    8     More than one '*' character not allowed.  Found on line 107 of test.config.
    9 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    10     More than one '@' character not allowed.  Found on line 113 of test.config.
    11 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    12     More than one '~' character not allowed.  Found on line 119 of test.config.
    13 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    14     Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
    15 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    16     Failed to read a metadata value on line 95 of test.config.
    17 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    18     Metadata type '99.999', found on line 101 of test.config, is not invalid.
    19 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    20     More than one '*' character not allowed.  Found on line 107 of test.config.
    21 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    22     More than one '@' character not allowed.  Found on line 113 of test.config.
    23 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    24     More than one '~' character not allowed.  Found on line 119 of test.config.
     67    Unallowable operation: fileName is NULL.
     68
     69---> TESTPOINT PASSED (psMetadataParseConfig{psMetadataParseConfig} | tst_psMetadataIO.c)
     70
     71/***************************** TESTPOINT ******************************************\
     72*             TestFile: tst_psMetadataIO.c                                         *
     73*            TestPoint: psMetadataParseConfig{psMetadataParseConfig}               *
     74*             TestType: Positive                                                   *
     75\**********************************************************************************/
     76
     77<DATE><TIME>|<HOST>|I|testMetadataParseConfig2
     78    Following should generate an error of duplicate key names
    2579<DATE><TIME>|<HOST>|E|psMetadataAddItem (FILE:LINENO)
    2680    Duplicate metadata item name is not allowed.  Use a psMetadataFlags option to allow such action.
    2781<DATE><TIME>|<HOST>|E|psMetadataAddV (FILE:LINENO)
    2882    Failed to add metadata item to metadata collection list.
    29 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    30     Duplicate Metadata item, speed, found on line 127 of test.config.  Overwrite not allowed.
    31 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    32     Failed to parse the value '9876.54qqq32' of metadata item xPosition, type F64, on line 89 of test.config.
    33 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    34     Failed to read a metadata value on line 95 of test.config.
    35 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    36     Metadata type '99.999', found on line 101 of test.config, is not invalid.
    37 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    38     More than one '*' character not allowed.  Found on line 107 of test.config.
    39 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    40     More than one '@' character not allowed.  Found on line 113 of test.config.
    41 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    42     More than one '~' character not allowed.  Found on line 119 of test.config.
    43 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    44     Unallowable operation: fileName is NULL.
    45 <DATE><TIME>|<HOST>|E|psMetadataParseConfig (FILE:LINENO)
    46     Failed to open file 'abcedfg'. Check if it exists and it has the proper permissions.
     83
     84---> TESTPOINT PASSED (psMetadataParseConfig{psMetadataParseConfig} | tst_psMetadataIO.c)
     85
  • trunk/psLib/test/collections/verified/tst_psMetadataIO.stdout

    r3779 r3945  
    1 /***************************** TESTPOINT ******************************************\
    2 *             TestFile: tst_psMetadataIO.c                                         *
    3 *            TestPoint: psMetadata{Test A - Read config file with overwrite set true} *
    4 *             TestType: Positive                                                   *
    5 \**********************************************************************************/
     1Double                    F64                                   1.234568  # This is a comment   
     2String                    STR    This is the string that forms the value  # comment             
     3boolean                   BOOL                                         1  # The value of 'boolean' is 'true'
     4@primes                   U8     2,3,5,7,11,13,17  # These are prime numbers
     5comment                   MULTI
     6comment                   STR                                       This
     7comment                   STR                                         is
     8comment                   STR                                          a
     9comment                   STR                                 non-unique
     10comment                   STR                                        key
     11Float                     F64                                   1.234560  # This generates a warning, and, if 'overwrite' is 'false', is ignored
     12boolean1                  BOOL                                         0  # The value of 'boolean' is 'false'
     13@negprimes                S8     -2,-3,-5,-7,-11,-13,-17,-19
     14@vector1                  U16    0,1,2,4,8
     15@vector2                  U32    0,8,16,32,64,128
     16@vector3                  U64    0,64,256
     17@vector4                  S16    -2,-1,0,1,2
     18@vector5                  S32    -4,-2,0,2,4,6
     19@vector6                  S64    -16,-4,0,4,16,36,64
     20@vector7                  F32    -1.03,1.04,-1.05,1.06
     21@vector8                  F64    -2.22,2.21,-2.2,2.19,-2.18
     22CELL.00                   METADATA
     23    EXTNAME                   STR                                      CCD00
     24    BIASSEC                   STR                                    BSEC-00
     25    CHIP                      STR                                    CHIP.00
    626
    7 Failed lines: 6 Expected: 6
    8 Contents of metadata list:
    9  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    10  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    11  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    12  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    13  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
    14  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    15  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    16  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    17  Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    18  Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    19  Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    20  Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    21  Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    22  Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    23  Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    24  Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    25  Key Name:    speed  Key mdType: 0x00000404 Key Value:          66.660  Key Comment:
     27CELL.01                   METADATA
     28    EXTNAME                   STR                                      CCD01
     29    BIASSEC                   STR                                    BSEC-01
     30    CHIP                      STR                                    CHIP.00
    2631
    27 Contents of metadata table:
    28  Key Name:  comment  Key mdType: 0x0001000a Key Value:                  Key Comment: List of Metadata Items
    29     Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    30     Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    31     Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    32     Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    33     Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    34     Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    35     Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    36     Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    37  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    38  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    39  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    40  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    41  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    42  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    43  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    44  Key Name:    speed  Key mdType: 0x00000404 Key Value:          66.660  Key Comment:
    45  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
     32MYCELL                    MULTI
     33MYCELL                    METADATA
     34    EXTNAME                   STR                                      CCD00
     35    BIASSEC                   STR                                    BSEC-00
     36    CHIP                      STR                                    CHIP.00
     37    NCELL                     S32                                         24
    4638
    47 ---> TESTPOINT PASSED (psMetadata{Test A - Read config file with overwrite set true} | tst_psMetadataIO.c)
     39MYCELL                    S32                                        123  # A number           
     40cell                      METADATA
     41    foo                       METADATA
     42    bar                       STR                                        BAZ
     43    ping                      STR                                       PONG
    4844
    49 /***************************** TESTPOINT ******************************************\
    50 *             TestFile: tst_psMetadataIO.c                                         *
    51 *            TestPoint: psMetadata{Test B - Read config file with overwrite set false} *
    52 *             TestType: Positive                                                   *
    53 \**********************************************************************************/
     45    EXTNAME                   STR                                      CCD00
     46    BIASSEC                   STR                                    BSEC-00
     47    CHIP                      STR                                    CHIP.00
     48    NCELL                     S32                                         12
    5449
    55 Failed lines: 7 Expected: 7 Contents of metadata list:
    56  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    57  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    58  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    59  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    60  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
    61  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    62  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    63  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    64  Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    65  Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    66  Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    67  Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    68  Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    69  Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    70  Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    71  Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    72  Key Name:    speed  Key mdType: 0x00000404 Key Value:          55.550  Key Comment:
    73 
    74 Contents of metadata table:
    75  Key Name:  comment  Key mdType: 0x0001000a Key Value:                  Key Comment: List of Metadata Items
    76     Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    77     Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    78     Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    79     Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    80     Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    81     Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    82     Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    83     Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    84  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    85  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    86  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    87  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    88  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    89  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    90  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    91  Key Name:    speed  Key mdType: 0x00000404 Key Value:          55.550  Key Comment:
    92  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
    93 
    94 ---> TESTPOINT PASSED (psMetadata{Test B - Read config file with overwrite set false} | tst_psMetadataIO.c)
    95 
    96 /***************************** TESTPOINT ******************************************\
    97 *             TestFile: tst_psMetadataIO.c                                         *
    98 *            TestPoint: psMetadata{Test C - Read config file without auto-allocation of metadata} *
    99 *             TestType: Positive                                                   *
    100 \**********************************************************************************/
    101 
    102 Failed lines: 6 Expected: 6 Contents of metadata list:
    103  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    104  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    105  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    106  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    107  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
    108  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    109  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    110  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    111  Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    112  Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    113  Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    114  Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    115  Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    116  Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    117  Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    118  Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    119  Key Name:    speed  Key mdType: 0x00000404 Key Value:          66.660  Key Comment:
    120 
    121 Contents of metadata table:
    122  Key Name:  comment  Key mdType: 0x0001000a Key Value:                  Key Comment: List of Metadata Items
    123     Key Name:  comment  Key mdType: 0x00010001 Key Value:            This  Key Comment:
    124     Key Name:  comment  Key mdType: 0x00010001 Key Value:              is  Key Comment:
    125     Key Name:  comment  Key mdType: 0x00010001 Key Value:              an  Key Comment:
    126     Key Name:  comment  Key mdType: 0x00010001 Key Value:            ugly  Key Comment:
    127     Key Name:  comment  Key mdType: 0x00010001 Key Value:         comment  Key Comment:
    128     Key Name:  comment  Key mdType: 0x00010001 Key Value:             but  Key Comment:
    129     Key Name:  comment  Key mdType: 0x00010001 Key Value:           still  Key Comment:
    130     Key Name:  comment  Key mdType: 0x00010001 Key Value:           valid  Key Comment:
    131  Key Name:   title2  Key mdType: 0x00010001 Key Value:  Good bye world  Key Comment: STRING or STR may be used as the string type
    132  Key Name:     time  Key mdType: 0x00000404 Key Value:        1234.568  Key Comment:
    133  Key Name: negatives  Key mdType: 0x00010002 Key Value:  [-1,-2,-3,...]  Key Comment:
    134  Key Name:       pi  Key mdType: 0x00000408 Key Value:           3.142  Key Comment: Definition of pi
    135  Key Name:   myBool  Key mdType: 0x00001301 Key Value:               0  Key Comment: F, f, 0, T, t, 1 are also acceptable
    136  Key Name:   primes  Key mdType: 0x00010002 Key Value:   [2,3,5,7,...]  Key Comment: These are prime numbers
    137  Key Name: altitude  Key mdType: 0x00000104 Key Value:           10000  Key Comment:
    138  Key Name:    speed  Key mdType: 0x00000404 Key Value:          66.660  Key Comment:
    139  Key Name:   title1  Key mdType: 0x00010001 Key Value:     Hello world  Key Comment: This is a comment for the string value
    140 
    141 ---> TESTPOINT PASSED (psMetadata{Test C - Read config file without auto-allocation of metadata} | tst_psMetadataIO.c)
    142 
    143 /***************************** TESTPOINT ******************************************\
    144 *             TestFile: tst_psMetadataIO.c                                         *
    145 *            TestPoint: psMetadataIO{Test D - Attempt to use null fileName argument} *
    146 *             TestType: Negative                                                   *
    147 *    ExpectedErrorText: Null failedLines not allowed                               *
    148 *  ExpectedStatusValue: 0                                                          *
    149 \**********************************************************************************/
    150 
    151 
    152 ---> TESTPOINT PASSED (psMetadata{Test D - Attempt to use null fileName argument} | tst_psMetadataIO.c)
    153 
    154 /***************************** TESTPOINT ******************************************\
    155 *             TestFile: tst_psMetadataIO.c                                         *
    156 *            TestPoint: psMetadataIO{Test E - Attempt to open nonexistant file}    *
    157 *             TestType: Negative                                                   *
    158 *    ExpectedErrorText: Error opening file                                         *
    159 *  ExpectedStatusValue: 0                                                          *
    160 \**********************************************************************************/
    161 
    162 
    163 ---> TESTPOINT PASSED (psMetadata{Test E - Attempt to open nonexistant file} | tst_psMetadataIO.c)
    164 
    165 /***************************** TESTPOINT ******************************************\
    166 *             TestFile: tst_psMetadataIO.c                                         *
    167 *            TestPoint: psMetadata{Test F - Free psMetadata}                       *
    168 *             TestType: Positive                                                   *
    169 \**********************************************************************************/
    170 
    171 
    172 ---> TESTPOINT PASSED (psMetadata{Test F - Free psMetadata} | tst_psMetadataIO.c)
    173 
  • trunk/psLib/test/collections/verified/tst_psMetadata_01.stdout

    r3779 r3945  
    4444 Key Name:   PCOUNT  Key mdType: 0x00000104  Key Value:               0  Key Comment: required keyword; must = 0
    4545 Key Name: XTENSION  Key mdType: 0x00010001  Key Value:      'IMAGE   '  Key Comment: IMAGE extension
    46  Key Name:   BITPIX  Key mdType: 0x0001000a  Key Value:                  Key Comment: List of Metadata Items
     46 Key Name:   BITPIX  Key mdType: 0x0001000a  Key Value:                  Key Comment:
    4747    Key Name:   BITPIX  Key mdType: 0x00000104  Key Value:             -64  Key Comment: number of bits per data pixel
    4848    Key Name:   BITPIX  Key mdType: 0x00000104  Key Value:             -64  Key Comment: number of bits per data pixel
    4949 Key Name:   GCOUNT  Key mdType: 0x00000104  Key Value:               1  Key Comment: required keyword; must = 1
    50  Key Name:  HISTORY  Key mdType: 0x0001000a  Key Value:                  Key Comment: List of Metadata Items
     50 Key Name:  HISTORY  Key mdType: 0x0001000a  Key Value:                  Key Comment:
    5151    Key Name:  HISTORY  Key mdType: 0x00010001  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
    5252    Key Name:  HISTORY  Key mdType: 0x00010001  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
     
    8181 Key Name:   GCOUNT  Key mdType: 0x00000104  Key Value:               1  Key Comment: required keyword; must = 1
    8282 Key Name:   BITPIX  Key mdType: 0x00000104  Key Value:             -64  Key Comment: number of bits per data pixel
    83  Key Name:  HISTORY  Key mdType: 0x0001000a  Key Value:                  Key Comment: List of Metadata Items
     83 Key Name:  HISTORY  Key mdType: 0x0001000a  Key Value:                  Key Comment:
    8484    Key Name:  HISTORY  Key mdType: 0x00010001  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
    8585    Key Name:  HISTORY  Key mdType: 0x00010001  Key Value:                  Key Comment: File modified by user 'harman' with fv  on 2004-08-04T<DATE>
Note: See TracChangeset for help on using the changeset viewer.