Index: trunk/psLib/src/xml/psXML.c
===================================================================
--- trunk/psLib/src/xml/psXML.c	(revision 4432)
+++ trunk/psLib/src/xml/psXML.c	(revision 4540)
@@ -1,15 +1,15 @@
-/** @file  psMetadataIO.c
+/** @file  psXML.c
 *
-*  @brief Contains metadata input/output functions.
+*  @brief Contains XML input/output functions.
 *
-*  This file defines functions to read and write metadata to/from an external file.
+*  This file defines functions to read metadata from an XML file.
 *
-*  @ingroup Metadata
+*  @ingroup XML
 *
 *  @author Ross Harman, MHPCC
 *  @author Eric Van Alst, MHPCC
 *
-*  @version $Revision: 1.34 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-06-30 00:04:12 $
+*  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-07-12 19:12:01 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -17,21 +17,14 @@
 
 #include <libxml/parser.h>
-#include <fitsio.h>
 #include <string.h>
 #include <ctype.h>
 #include <limits.h>
 
-#include "psAbort.h"
-#include "psType.h"
+#include "psXML.h"
 #include "psMemory.h"
 #include "psError.h"
 #include "psString.h"
-#include "psList.h"
-#include "psHash.h"
-#include "psVector.h"
-#include "psMetadata.h"
-#include "psMetadataIO.h"
 #include "psConstants.h"
-#include "psAstronomyErrors.h"
+#include "psErrorText.h"
 
 /******************************************************************************/
@@ -39,18 +32,4 @@
 /******************************************************************************/
 
-/** Check for FITS errors */
-#define FITS_ERROR(STRING,PS_ERROR)                                                                          \
-fits_get_errstatus(status, fitsErr);                                                                         \
-psError(PS_ERR_IO,true, STRING, PS_ERROR, fitsErr);                                                          \
-status = 0;                                                                                                  \
-fits_close_file(fd, &status);                                                                                \
-if(status){                                                                                                  \
-    fits_get_errstatus(status, fitsErr);                                                                     \
-    psError(PS_ERR_IO,true, "Couldn't close FITS file. FITS error: %s", fitsErr);                            \
-}                                                                                                            \
-status = 0;                                                                                                  \
-psFree(output);                                                                                              \
-return NULL;
-
 /** Maximum size of a FITS line */
 #define FITS_LINE_SIZE 80
@@ -59,163 +38,7 @@
 #define MAX_STRING_LENGTH 256
 
-
-/******************************************************************************/
-/*  TYPE DEFINITIONS                                                          */
-/******************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FILE STATIC VARIABLES                                                    */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
-/*****************************************************************************/
-
-static void saxEndElement(void *ctx, const xmlChar *tagName);
-static void initVectorXml(void *ctx, char *tagName);
-static void initMetadataItemXml(void *ctx, char *tagName);
-static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
-static psMetadata* getMetadataType(char *linePtr);
-static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
-;
-static void parseLevelInfoFree(p_psParseLevelInfo* info);
-static psBool parseLine(psS32* level,   psArray* levelArray,
-                        char*  linePtr, psS32 lineCount,     char* fileName, psBool overwrite);
-static psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
-                                char* linePtr, psS32  lineCount, char*    fileName,    psMetadataFlags flags);
-
-static void parseLevelInfoFree(p_psParseLevelInfo* info)
-{
-    psFree(info->nonUniqueKeyArray);
-    psFree(info->typeArray);
-    psFree(info->templateArray);
-    psFree(info->name);
-    psFree(info->metadata);
-}
-
-// Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
-// must be null terminated.
-psBool ignoreLine(char *inString)
-{
-    while(*inString!='\0' && *inString!='#') {
-        if(!isspace(*inString)) {
-            return false;
-        }
-        inString++;
-    }
-
-    return true;
-}
-
-
-//  Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
-//  terminated copy of the original input string.
-char *cleanString(char *inString, psS32 sLen, psBool ignoreComment)
-{
-    char *ptrB = NULL;
-    char *ptrE = NULL;
-    char *cleaned = NULL;
-
-    // Initialize begining of string pointer
-    ptrB = inString;
-
-    // Skip over leading # or whitespace
-    if(ignoreComment) {
-        while (isspace(*ptrB) || *ptrB=='#') {
-            ptrB++;
-        }
-    } else {
-        while (isspace(*ptrB)) {
-            ptrB++;
-        }
-    }
-
-    // Skip over trailing whitespace, null terminators, and # characters
-    ptrE = inString + sLen;
-    if(ignoreComment) {
-        while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
-            ptrE--;
-        }
-    } else {
-        while(isspace(*ptrE) || *ptrE=='\0') {
-            ptrE--;
-        }
-    }
-
-    // Length, sLen, does not include '\0'
-    sLen = ptrE - ptrB + 1;
-
-    // Adds '\0' to end of string and +1 to sLen
-    if(sLen < 0 ) {
-        cleaned = NULL;
-    } else {
-        cleaned = psStringNCopy(ptrB, sLen);
-    }
-
-    return cleaned;
-}
-
-// Count repeat occurances of a single character within a line. The input string must be null terminated.
-psS32 repeatedChars(char *inString, char ch)
-{
-    psS32 count = 0;
-
-    while(*inString!='\0') {
-        if(*inString == ch) {
-            count++;
-        }
-        inString++;
-    }
-
-    return count;
-}
-
-// Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
-// the beginning of the string. Tokens are newly allocated null terminated strings.
-char* getToken(char **inString, char *delimiter, psS32 *status, psBool ignoreComment)
-{
-    char *cleanToken = NULL;
-    char *convertChar = NULL;
-    psS32 sLen = 0;
-
-    // Convert tab characters to white space
-    while((convertChar=strchr(*inString,'\t')) != NULL ) {
-        *convertChar = ' ';
-    }
-
-    // Skip over leading whitespace
-    while(isspace(**inString)) {
-        (*inString)++;
-    }
-
-    // Length of token, not including delimiter
-    sLen = strcspn(*inString, delimiter);
-    if(sLen) {
-
-        // Create new, cleaned, and null terminated token
-        cleanToken = cleanString(*inString, sLen,ignoreComment);
-
-        // Move to end of token
-        (*inString) += sLen;
-    } else if(**inString!='\0' && sLen==0) {
-        *status = 1;
-    }
-
-    return cleanToken;
-}
-
 // Returns single parsed value as a double precision number. The input string must be cleaned and null
 // terminated.
-double parseValue(char *inString, psS32 *status)
+static double parseValue(char *inString, psS32 *status)
 {
     char *end = NULL;
@@ -233,5 +56,5 @@
 
 /** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */
-psBool parseBool(char *inString, psS32 *status)
+static psBool parseBool(char *inString, psS32 *status)
 {
     psBool value = false;
@@ -250,5 +73,5 @@
 
 /** Returns parsed vector filled with with data. The input string must be null terminated. */
-psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
+static psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
 {
     char*      end       = NULL;
@@ -332,808 +155,4 @@
 
     return vec;
-}
-
-/*****************************************************************************/
-/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
-/*****************************************************************************/
-
-p_psParseLevelInfo* p_psParseLevelInfoAlloc(void)
-{
-
-    p_psParseLevelInfo* info = NULL;
-
-    // Allocate memory for parse level info
-    info = (p_psParseLevelInfo*)psAlloc(sizeof(p_psParseLevelInfo));
-
-    // If allocation successful then initialize members
-    if(info != NULL) {
-
-        info->nonUniqueKeyArray = psArrayAlloc(10);
-        info->nonUniqueKeyArray->n = 0;
-
-        info->typeArray = psArrayAlloc(10);
-        info->typeArray->n = 0;
-
-        info->templateArray = psArrayAlloc(10);
-        info->templateArray->n = 0;
-
-        info->metadata = NULL;
-        info->name = NULL;
-
-        // Set memory deallocator
-        psMemSetDeallocator(info,(psFreeFunc)parseLevelInfoFree);
-    }
-    return info;
-}
-
-bool psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* item)
-{
-    psMetadataType type;
-    psBool success = true;
-
-    PS_ASSERT_PTR_NON_NULL(fd, success);
-    PS_ASSERT_PTR_NON_NULL(format, success);
-    PS_ASSERT_PTR_NON_NULL(item, success);
-
-    type = item->type;
-
-    // determining the format type
-    char* fType = strchr(format,'%');
-    if (fType == NULL) {
-        // well, the format contains no reference to the metadataItem's data:
-        // that is truly trival to do!
-        fprintf(fd,format);
-        return success;
-    }
-
-    // skip over any format modifiers
-    const char* formatEnd = format+strlen(format);
-    while ( (fType < formatEnd) &&
-        (strchr(" +-01234567890.$#, hlL",*(++fType)) != NULL) ) {}
-
-    #define METADATAITEM_NUMERIC_CAST(FORMAT_TYPE) { \
-        switch(type) { \
-        case PS_META_BOOL: \
-            fprintf(fd, format, (FORMAT_TYPE) item->data.B); \
-            break; \
-        case PS_META_S32: \
-            fprintf(fd,format,(FORMAT_TYPE)  item->data.S32); \
-            break; \
-        case PS_META_F32: \
-            fprintf(fd, format,(FORMAT_TYPE)  item->data.F32); \
-            break; \
-        case PS_META_F64: \
-            fprintf(fd, format,(FORMAT_TYPE) item->data.F64); \
-            break; \
-        default: \
-            psError(PS_ERR_BAD_PARAMETER_TYPE,true, \
-                    PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type); \
-            success = false; \
-        } \
-    }
-
-    switch(*fType) {
-    case 'd':
-    case 'i':
-    case 'c':
-        METADATAITEM_NUMERIC_CAST(int)
-        break;
-    case 'o':
-    case 'u':
-    case 'x':
-    case 'X':
-        METADATAITEM_NUMERIC_CAST(unsigned int)
-        break;
-    case 'e':
-    case 'E':
-    case 'f':
-    case 'F':
-    case 'g':
-    case 'G':
-    case 'a':
-    case 'A':
-        METADATAITEM_NUMERIC_CAST(double)
-        break;
-    case 's':
-        if (type == PS_META_STR) {
-            fprintf(fd,format,(char*)item->data.V);
-        } else {
-            psError(PS_ERR_BAD_PARAMETER_TYPE,true,
-                    PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
-            success = false;
-        }
-        break;
-    case 'p':
-        fprintf(fd,format,item->data.V);
-        break;
-    default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
-                PS_ERRORTEXT_psMetadata_FORMAT_INVALID, *fType);
-        break;
-    }
-
-    return success;
-}
-
-
-psMetadata* psMetadataReadHeader(psMetadata* output, char *extName, psS32 extNum, char *fileName)
-{
-    psBool tempBool;
-    psBool success;
-    char keyType;
-    char keyName[FITS_LINE_SIZE];
-    char keyValue[FITS_LINE_SIZE];
-    char keyComment[FITS_LINE_SIZE];
-    char fitsErr[MAX_STRING_LENGTH];
-    psS32 i;
-    psS32 hduType = 0;
-    psS32 status = 0;
-    psS32 numKeys = 0;
-    psS32 keyNum = 0;
-    fitsfile *fd = NULL;
-
-    PS_ASSERT_PTR_NON_NULL(fileName,NULL);
-
-    fits_open_file(&fd, fileName, READONLY, &status);
-    if(fd == NULL || status != 0) {
-        FITS_ERROR("FITS error while opening file: %s %s", fileName);
-        return NULL;
-    }
-
-    if (extName == NULL && extNum < 1) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                PS_ERRORTEXT_psMetadataIO_EXTNUM_NOTPOSITIVE,
-                extNum);
-        return NULL;
-    }
-
-    // Allocate metadata if user didn't
-    if (output == NULL) {
-        output = psMetadataAlloc();
-    }
-
-    // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.
-    if (extName != NULL) {
-        if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {
-            FITS_ERROR("FITS error while locating header %s: %s", extName);
-        }
-    } else {
-        if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {
-            FITS_ERROR("FITS error while locating header %d: %s", extNum);
-        }
-    }
-
-    // Get number of key names
-    if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
-        FITS_ERROR("FITS error while reading key %d: %s", keyNum);
-    }
-
-    // Get each key name. Keywords start at one.
-    for (i = 1; i <= numKeys; i++) {
-        if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
-            FITS_ERROR("FITS error while reading key %d: %s", keyNum);
-        }
-        if (fits_get_keytype(keyValue, &keyType, &status) != 0) {
-            fits_get_errstatus(status, fitsErr);
-            if (status != VALUE_UNDEFINED) {
-                FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
-            } else {
-                // Some keywords are still valid if they don't have a type (like COMMENTS and HISTORY)
-                keyType = 'C';
-                status = 0;
-            }
-        }
-
-        switch (keyType) {
-        case 'I':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
-                                    PS_META_S32 | PS_META_DUPLICATE_OK,
-                                    keyComment, atoi(keyValue));
-            break;
-        case 'F':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
-                                    PS_META_F64 | PS_META_DUPLICATE_OK,
-                                    keyComment, atof(keyValue));
-            break;
-        case 'C':
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
-                                    PS_META_STR | PS_META_DUPLICATE_OK,
-                                    keyComment, keyValue);
-            break;
-        case 'L':
-            tempBool = (keyValue[0] == 'T') ? 1 : 0;
-            success = psMetadataAdd(output, PS_LIST_TAIL, keyName,
-                                    PS_META_BOOL | PS_META_DUPLICATE_OK,
-                                    keyComment, tempBool);
-            break;
-        case 'U':
-        case 'X':
-        default:
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FITS_METATYPE_INVALID, keyType);
-            return output;
-        }
-
-        if (!success) {
-            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadataIO_ADD_FAILED, keyName);
-            return output;
-        }
-    }
-
-    return output;
-}
-
-static psMetadata* getMetadataType(char* linePtr)
-{
-    psMetadata*     metadataTemplate = NULL;
-    psS32           status           = 0;
-    char*           token            = NULL;
-    psMetadataItem* tempItem         = NULL;
-
-    // Loop through line and generate metadata items for each token found
-    while((token = getToken(&linePtr," ",&status,false)) != NULL ) {
-
-        // If not allocated then allocate new metadata
-        if(metadataTemplate == NULL) {
-            metadataTemplate = psMetadataAlloc();
-        }
-
-        // Look for comment indicator #
-        if(strstr(token,"#") != 0) {
-            psFree(token);
-            break;
-        }
-
-        // Create metadata item to represent token read
-        tempItem = psMetadataItemAllocStr(token,"","");
-        if(tempItem == NULL) {
-            psFree(metadataTemplate);
-            psFree(token);
-            metadataTemplate = NULL;
-            break;
-        }
-
-        // Add item to template
-        if(!psMetadataAddItem(metadataTemplate, tempItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
-            psFree(metadataTemplate);
-            psFree(tempItem);
-            psFree(token);
-            metadataTemplate = NULL;
-            break;
-        }
-        psFree(tempItem);
-        psFree(token);
-    }
-
-    return metadataTemplate;
-}
-
-static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)
-{
-    psMetadata*      md           = NULL;
-    psS32            items        = 0;
-    char*            token        = NULL;
-    psS32            status       = 0;
-    psMetadataItem*  mdItem       = NULL;
-    psMetadataItem*  templateItem = NULL;
-    psListIterator*  iter         = NULL;
-
-    // Determine the number of items in template
-    items = template->list->size;
-    if(items > 0 ) {
-
-        // Allocate metadata
-        md = psMetadataAlloc()
-             ;
-
-        // Point to first item in template
-        iter = psListIteratorAlloc(template->
-                                   list,PS_LIST_HEAD,true);
-
-        // For each item in template parse line string for values
-        for(psS32 i = 0;
-                i < items;
-                i++) {
-
-            // Get template item
-            templateItem = psListGetAndIncrement(iter)
-                           ;
-            if(templateItem == NULL) {
-                psFree(md);
-                md = NULL;
-                break;
-            }
-
-            // Get the next token on the line
-            token = getToken(&linePtr," ",&status,false);
-            if(token != NULL) {
-                // Allocate metadata item
-                mdItem = psMetadataItemAllocStr(templateItem->name,templateItem->comment,token);
-                if(mdItem == NULL) {
-                    psFree(md);
-                    md = NULL;
-                    psFree(token);
-                    break;
-                }
-                // Add item to metadata
-                if(!psMetadataAddItem(md, mdItem, PS_LIST_TAIL, PS_META_DEFAULT)) {
-                    psFree(md);
-                    md = NULL;
-                    psFree(mdItem);
-                    psFree(token);
-                    break;
-                }
-                psFree(mdItem);
-            } else {
-                // Missing items
-                psFree(md);
-                md = NULL;
-                break;
-            }
-
-            psFree(token);
-        }
-        psFree(iter);
-    }
-    return md;
-}
-
-psBool parseMetadataItem(char* keyName, psS32* level,     psArray* levelArray,
-                         char* linePtr, psS32  lineCount, char*    fileName,   psMetadataFlags flags)
-{
-    psBool               returnValue   = true;
-    psBool               addStatus     = false;
-    psMetadataType       mdType        = PS_META_UNKNOWN;
-    psElemType           vectorType    = PS_TYPE_S8;
-    char*                strType       = NULL;
-    char*                strValue      = NULL;
-    char*                strComment    = NULL;
-    psS32                status        = 0;
-    psMetadata*          md            = NULL;
-    psF64                tempDbl       = 0.0;
-    psBool               tempBool      = false;
-    psS32                tempInt       = 0;
-    psVector*            tempVec       = NULL;
-    char*                tempStr       = NULL;
-    psArray*             nonUniqueKeys = NULL;
-    psBool               typeFound     = false;
-    psArray*             typeArray     = NULL;
-    psArray*             templateArray = NULL;
-    psMetadata*          tempMeta      = NULL;
-    p_psParseLevelInfo*  nextLevelInfo = NULL;
-
-    // Get the metadata item type
-    strType = getToken(&linePtr, " ", &status,true);
-
-    // Check for no type
-    if(strType==NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,
-                fileName);
-        returnValue = false;
-    } else {
-
-        // Set metadata type based on type token
-
-        // Check if the keyName specifies a vector and if so use strType token to find vector type
-        if(*keyName == '@') {
-            mdType = PS_META_VEC;
-            // Get the type of vector
-            if(!strncmp(strType, "U8", 2)) {
-                vectorType = PS_TYPE_U8;
-            } else if (!strncmp(strType,"U16",3)) {
-                vectorType = PS_TYPE_U16;
-            } else if (!strncmp(strType,"U32",3)) {
-                vectorType = PS_TYPE_U32;
-            } else if (!strncmp(strType,"U64",3)) {
-                vectorType = PS_TYPE_U64;
-            } else if (!strncmp(strType,"S8",2)) {
-                vectorType = PS_TYPE_S8;
-            } else if (!strncmp(strType,"S16",3)) {
-                vectorType = PS_TYPE_S16;
-            } else if (!strncmp(strType,"S32",3)) {
-                vectorType = PS_TYPE_S32;
-            } else if (!strncmp(strType,"S64",3)) {
-                vectorType = PS_TYPE_S64;
-            } else if (!strncmp(strType,"F32",3)) {
-                vectorType = PS_TYPE_F32;
-            } else if (!strncmp(strType,"F64",3)) {
-                vectorType = PS_TYPE_F64;
-            } else {
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, "", keyName,
-                        strType, lineCount, fileName);
-                psFree(strType);
-                return false;
-            }
-        } else if(!strncmp(strType, "STR", 3)) {
-            mdType = PS_META_STR;
-        } else if(!strncmp(strType, "BOOL", 4)) {
-            mdType = PS_META_BOOL;
-        } else if(!strncmp(strType, "S32", 3)) {
-            mdType = PS_META_S32;
-        } else if(!strncmp(strType, "F32", 3)) {
-            mdType = PS_META_F32;
-        } else if(!strncmp(strType, "F64", 3)) {
-            mdType = PS_META_F64;
-        } else if(!strncmp(strType, "MULTI", 5)) {
-            mdType = PS_META_MULTI;
-        } else if(!strncmp(strType, "METADATA", 8)) {
-            mdType = PS_META_META;
-        } else {
-            // Search through user types
-            typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
-            templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
-            for(psS32 k = 0; k < typeArray->n; k++) {
-                if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
-                    tempMeta = setMetadataItem((psMetadata*)templateArray->data[k],linePtr);
-                    if(tempMeta != NULL) {
-                        // Add metadata item
-                        md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
-                        addStatus = psMetadataAdd(md,PS_LIST_TAIL,keyName,PS_META_META | flags,"",tempMeta);
-                        // Check for add failure
-                        if (! addStatus) {
-                            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM,
-                                    keyName, lineCount, fileName);
-                            psFree(strType);
-                            psFree(tempMeta);
-                            return false;
-                        }
-                        psFree(tempMeta);
-                    } else {
-                        // Metadata type read error
-                        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,
-                                keyName,lineCount,fileName);
-                        psFree(strType);
-                        return false;
-                    }
-                    typeFound = true;
-                    break;
-                }
-            }
-            if(!typeFound) {
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
-                        strType, lineCount,fileName);
-                psFree(strType);
-                return false;
-            } else {
-                psFree(strType);
-                return true;
-            }
-        }
-    }
-
-    // If type is not MULTI or META then get the value and comment
-    if((mdType != PS_META_MULTI) && (mdType != PS_META_META)) {
-        // Get the metadata item value if there is one.
-        status = 0;
-        strValue = getToken(&linePtr, "#", &status,true);
-        if(status) {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                    fileName);
-            psFree(strType);
-            psFree(strValue);
-            return false;
-        }
-        if(strValue==NULL) {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                    fileName);
-            psFree(strType);
-            psFree(strValue);
-            return false;
-        }
-        // Not all lines will have comments, so NULL is ok.
-        status = 0;
-        strComment = getToken(&linePtr,"~", &status,true);
-        if(status) {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
-                    fileName);
-            psFree(strType);
-            psFree(strValue);
-            psFree(strComment);
-        }
-    }
-
-    // Need to add item to metadata so get pointer to metadata
-    status = 0;
-    md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;
-    nonUniqueKeys = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray;
-    switch(mdType) {
-    case PS_META_STR:
-        addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
-                                  mdType | flags,
-                                  strComment, strValue);
-        break;
-    case PS_META_BOOL:
-        tempBool = parseBool(strValue, &status);
-        if(!status) {
-            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
-                                      mdType | flags,
-                                      strComment, tempBool);
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
-                    strType, lineCount, fileName);
-            returnValue = false;
-        }
-        break;
-    case PS_META_F32:
-    case PS_META_F64:
-        tempDbl = parseValue(strValue, &status);
-        if(!status) {
-            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
-                                      mdType | flags,
-                                      strComment, tempDbl);
-        } else {
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName, strType, lineCount,
-                    fileName);
-            returnValue = false;
-        }
-        break;
-    case PS_META_S32:
-        tempInt = (psS32)parseValue(strValue, &status);
-        if(!status) {
-            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,
-                                      mdType | flags,
-                                      strComment, tempInt);
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
-                    strType, lineCount, fileName);
-            returnValue = false;
-        }
-        break;
-    case PS_META_VEC:
-        tempVec = parseVector(strValue, vectorType, &status);
-        if(!status) {
-            addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName+1,
-                                      mdType | flags,
-                                      strComment, tempVec);
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,
-                    strType, lineCount, fileName);
-            returnValue = false;
-        }
-        psFree(tempVec);
-        break;
-    case PS_META_MULTI:
-        // Add key to non-unique array of keys
-        // Check for duplicate MULTI lines
-        addStatus = true;
-        for(psS32 k=0; k < nonUniqueKeys->n; k++) {
-            if(strcmp(keyName,(char*)nonUniqueKeys->data[k]) == 0) {
-                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_DUPLICATE_MULTI,
-                        lineCount,fileName);
-                psFree(strType);
-                return false;
-            }
-        }
-        tempStr = psStringCopy(keyName);
-        nonUniqueKeys = psArrayAdd(nonUniqueKeys,0,tempStr);
-        addStatus = true;
-        psFree(tempStr);
-        break;
-    case PS_META_META:
-        // Create next level info
-        nextLevelInfo = p_psParseLevelInfoAlloc();
-        // Create new metadata
-        nextLevelInfo->metadata = psMetadataAlloc();
-        // Save name of metadata
-        nextLevelInfo->name = psStringCopy(keyName);
-        // Add next level to levelArray
-        levelArray = psArrayAdd(levelArray,1,nextLevelInfo);
-        psFree(nextLevelInfo);
-        // Increment level counter
-        (*level)++;
-        addStatus = true;
-        break;
-    default:
-        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
-                lineCount,fileName);
-        break;
-    }
-
-    // Check if the add status was successful
-    if (! addStatus) {
-        //        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, keyName, lineCount,
-        //                fileName);
-        returnValue = false;
-    }
-
-    psFree(strComment);
-    psFree(strValue);
-    psFree(strType);
-
-    return returnValue;
-}
-
-psBool parseLine(psS32* level,     psArray* levelArray, char*  linePtr,
-                 psS32  lineCount, char*    fileName,   psBool overwrite)
-{
-    psBool              returnValue    = true;
-    psMetadataFlags     flags          = PS_META_DEFAULT;
-    char*               keyName        = NULL;
-    psS32               status         = 0;
-    psS32               limit          = 0;
-    psMetadata*         tempTemplate   = NULL;
-    char*               strType        = NULL;
-    psArray*            typeArray      = NULL;
-    psArray*            templateArray  = NULL;
-    p_psParseLevelInfo* upperLevelInfo = NULL;
-    p_psParseLevelInfo* lowerLevelInfo = NULL;
-    psBool              addStatus      = 0;
-
-    // Set flags if overwrite specified
-    if(overwrite) {
-        flags = PS_META_REPLACE;
-    }
-
-    // If line is not a comment or blank, then extract data
-    if(!ignoreLine(linePtr)) {
-
-        // Check for more than one '@' in a line
-        if(repeatedChars(linePtr, '@') > 1) {
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);
-            return false;
-        }
-
-        // Get metadata item name
-        keyName = getToken(&linePtr, " ", &status,true);
-        if(status) {
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "keyName", lineCount, fileName);
-            psFree(keyName);
-            return false;
-        }
-
-        // Check for special keyName values "TYPE", "END"
-        if(strcmp(keyName,"TYPE") == 0 ) {
-            // Get the type name
-            strType = getToken(&linePtr," ",&status,true);
-            if(strType == NULL) {
-                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,"type",lineCount,
-                        fileName);
-                psFree(keyName);
-                return false;
-            }
-            tempTemplate = getMetadataType(linePtr);
-            // Check if type was parsed succesfully
-            if(tempTemplate != NULL) {
-                // Access type array
-                typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;
-                // Check if type already exists in array
-                for(psS32 k=0; k < typeArray->n; k++) {
-                    // Compare type name with the list of current types
-                    if(strcmp(strType,(char*)typeArray->data[k]) == 0) {
-                        psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_TYPE_DUPLICATE,
-                                strType,lineCount,fileName);
-                        psFree(tempTemplate);
-                        psFree(keyName);
-                        psFree(strType);
-                        return false;
-                    }
-                }
-                // Add key name to array of type
-                typeArray = psArrayAdd(typeArray,1,strType);
-                // Add template to array of templates
-                templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;
-                templateArray = psArrayAdd(templateArray,1,tempTemplate);
-                psFree(tempTemplate);
-            } else {
-                psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,
-                        strType,lineCount,fileName);
-                psFree(keyName);
-                psFree(strType);
-                return false;
-            }
-            psFree(strType);
-        } else if (strcmp(keyName,"END") == 0 ) {
-            if(*level > 0) {
-                upperLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level-1]));
-                lowerLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level]));
-                // Check name in nonunique list
-                for(psS32 k=0; k < upperLevelInfo->nonUniqueKeyArray->n; k++) {
-                    if(strcmp(upperLevelInfo->nonUniqueKeyArray->data[k],lowerLevelInfo->name) == 0) {
-                        flags = PS_META_DUPLICATE_OK;
-                        break;
-                    }
-                }
-                // Add metadata to upper level metadata
-                addStatus = psMetadataAdd(upperLevelInfo->metadata,
-                                          PS_LIST_TAIL,lowerLevelInfo->name,
-                                          PS_META_META | flags,
-                                          "",
-                                          lowerLevelInfo->metadata);
-                if(!addStatus) {
-                    psFree(keyName);
-                    return false;
-                } else {
-                    // Remove lower info level
-                    if(!psArrayRemove(levelArray,levelArray->data[*level])) {
-                        psFree(keyName);
-                        return false;
-                    }
-                    psFree(lowerLevelInfo);
-                    (*level)--;
-                }
-            } else {
-                psFree(keyName);
-                return false;
-            }
-        } else {
-            // Check if key name present in array of non-unique key names
-            limit = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray->n;
-            for(psS32 k=0; k < limit; k++) {
-                char* name = (char*)((p_psParseLevelInfo*)
-                                     (levelArray->data[*level]))->nonUniqueKeyArray->data[k];
-                if(strcmp(name,keyName) == 0) {
-                    flags = PS_META_DUPLICATE_OK;
-                }
-            }
-            // Parse metadataItem
-            if(!parseMetadataItem(keyName,level, levelArray, linePtr, lineCount, fileName, flags)) {
-                psFree(keyName);
-                return false;
-            }
-        }
-        psFree(keyName);
-    }
-    return returnValue;
-}
-
-psMetadata* psMetadataConfigParse(psMetadata* md, unsigned int *nFail, const char *fileName, bool overwrite)
-{
-    FILE*               fp                   = NULL;
-    char*               line                 = NULL;
-    char*               linePtr              = NULL;
-    psArray*            parseLevelInfoArray  = NULL;
-    psS32               lineCount            = 0;
-    psS32               nestingLevel         = 0;
-    p_psParseLevelInfo* topLevelInfo         = NULL;
-
-    // Check for NULL file name
-    PS_ASSERT_PTR_NON_NULL(fileName,NULL);
-
-    // Check for NULL nFail
-    PS_ASSERT_PTR_NON_NULL(nFail,NULL);
-
-    // Attempt to open specified file
-    if((fp=fopen(fileName, "r")) == NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
-        return NULL;
-    }
-
-    // Allocate metadata if necessary
-    if (md == NULL) {
-        md = psMetadataAlloc();
-    }
-
-    // Allocate array to store parse level information
-    parseLevelInfoArray = psArrayAlloc(10);
-    parseLevelInfoArray->n = 0;
-
-    // Set parse level info for the top level
-    topLevelInfo = p_psParseLevelInfoAlloc();
-    topLevelInfo->metadata = psMemIncrRefCounter(md);
-    parseLevelInfoArray = psArrayAdd(parseLevelInfoArray,1,topLevelInfo);
-    psFree(topLevelInfo);
-
-    // Create reusable line for continuous read
-    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
-
-    // While loop to parse the file
-    while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
-
-        // Initialize variables for new line
-        linePtr = line;
-        lineCount++;
-
-        if(!parseLine(&nestingLevel,parseLevelInfoArray,linePtr,lineCount,(char*)fileName,overwrite)) {
-            (*nFail)++;
-        }
-    }
-
-    // Free parse array and line buffer
-    psFree(parseLevelInfoArray);
-    psFree(line);
-
-    return md;
 }
 
