Index: trunk/psLib/src/astronomy/psDB.c
===================================================================
--- trunk/psLib/src/astronomy/psDB.c	(revision 3690)
+++ 	(revision )
@@ -1,1705 +1,0 @@
-/** @file  psDB.c
- *
- * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
- * vim: set cindent ts=8 sw=4 expandtab:
- *
- *  @brief database functions
- *
- *  This file contains functions that perform basic database operations.  MySQL
- *  4.1.2 or newer is required.
- *
- *  @author Aaron Culliney
- *  @author Joshua Hoblitt
- *
- *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-04-06 01:12:58 $
- *
- *  Copyright 2005 Joshua Hoblitt, University of Hawaii
- */
-
-#ifdef BUILD_PSDB
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-#include <mysql.h>
-#include <mysql_com.h> // enum_field_types
-
-#include "psDB.h"
-#include "psMemory.h"
-#include "psAbort.h"
-#include "psError.h"
-#include "psString.h"
-
-
-typedef struct
-{
-    enum enum_field_types type;
-    bool            isUnsigned;
-}
-mysqlType;
-
-// database utility functions
-static bool     psDBRunQuery(psDB *dbh, const char *query);
-static inline bool psDBPackRow(MYSQL_BIND *bind, psMetadata *values, psU32 paramCount);
-
-// SQL generation functions
-static char    *psDBGenerateCreateTableSQL(const char *tableName, psMetadata *where);
-static char    *psDBGenerateSelectRowSQL(const char *tableName, const char *col, psMetadata *where, psU64 limit);
-static char    *psDBGenerateInsertRowSQL(const char *tableName, psMetadata *row);
-static char    *psDBGenerateUpdateRowSQL(const char *tableName, psMetadata *where, psMetadata *values);
-static char    *psDBGenerateDeleteRowSQL(const char *tableName, psMetadata *where);
-static char    *psDBGenerateWhereSQL(psMetadata *where);
-static char    *psDBGenerateSetSQL(psMetadata *set
-                                  );
-
-// lookup table functions
-static psElemType psDBMySQLToPType(enum enum_field_types type, unsigned int flags);
-static char    *psDBPTypeToSQL(psElemType pType);
-static mysqlType *psDBPTypeToMySQL(psElemType pType);
-
-static psHash  *psDBGetPTypeToSQLTable(void);
-static void     psDBPTypeToSQLTableCleanup(void);
-
-static psHash  *psDBGetSQLToPTypeTable(void);
-static void     psDBSQLToPTypeTableCleanup(void);
-
-static psHash  *psDBGetMySQLToSQLTable(void);
-static void     psDBMySQLToSQLTableCleanup(void);
-
-static psHash  *psDBGetPTypeToMySQLTable(void);
-static void     psDBPTypeToMySQLTableCleanup(void);
-
-static psPtr    psDBMySQLTypeAlloc(enum enum_field_types type, bool isUnsigned);
-static void     psDBAddToLookupTable(psHash *lookupTable, psU32 type, const char *string);
-static void     psDBAddVoidToLookupTable(psHash *lookupTable, psU32 type, psPtr value);
-
-// pType utility functions
-static psPtr    psDBGetPTypeNaN(psElemType pType);
-static bool     psDBIsPTypeNaN(psElemType pType, psPtr data);
-
-// string utility functions
-static char    *psDBIntToString(psU64 n);
-static ssize_t  psStringAppend(char **dest, const char *format, ...);
-static ssize_t  psStringPrepend(char **dest, const char *format, ...);
-
-
-// public functions
-/*****************************************************************************/
-
-psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname)
-{
-    MYSQL           *mysql;
-    psDB            *dbh;
-
-    mysql = mysql_init(NULL);
-    if (!mysql) {
-        psAbort(__func__, "mysql_init(), out of memory.");
-    }
-
-    if (!mysql_real_connect(mysql, host, user, passwd, dbname, 0, NULL, 0)) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to connect to database.  Error: %s", mysql_error(mysql));
-
-        mysql_close(mysql);
-
-        return NULL;
-    }
-
-    dbh = psAlloc(sizeof(psDB));
-
-    dbh->mysql = mysql;
-
-    return dbh;
-}
-
-void psDBCleanup(psDB *dbh)
-{
-    mysql_close(dbh->mysql);
-    dbh->mysql = NULL;
-    psFree(dbh);
-
-    // ASC WARNING NOTE: the psDBSQLToPTypeTableCleanup cleanup routine
-    // needs to be called first because it refers to
-    // psDBGetPTypeToSQLTable ...
-    psDBSQLToPTypeTableCleanup();
-    psDBMySQLToSQLTableCleanup();
-    psDBPTypeToSQLTableCleanup();
-    psDBPTypeToMySQLTableCleanup();
-}
-
-bool psDBCreate(psDB *dbh, const char *dbname)
-{
-    char            *query = NULL;
-    bool            status;
-
-    psStringAppend(&query, "CREATE DATABASE %s", dbname);
-
-    // the MySQL C API notes that mysql_create_db() is deprecated
-    status = psDBRunQuery(dbh, query);
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to create new database.");
-    }
-
-    psFree(query);
-
-    return status;
-}
-
-bool psDBChange(psDB *dbh, const char *dbname)
-{
-    if (mysql_select_db(dbh->mysql, dbname) != 0) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to change database.  Error: %s", mysql_error(dbh->mysql));
-
-        return false;
-    }
-
-    return true;
-}
-
-bool psDBDrop(psDB *dbh, const char *dbname)
-{
-    char            *query = NULL;
-    bool            status;
-
-    psStringAppend(&query, "DROP DATABASE %s", dbname);
-
-    // the MySQL C API notes that mysql_drop_db() is deprecated
-    status = psDBRunQuery(dbh, query);
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to drop database.");
-    }
-
-    psFree(query);
-
-    return status;
-}
-
-bool psDBCreateTable(psDB *dbh, const char *tableName, psMetadata *md)
-{
-    char            *query;
-    bool            status;
-
-    query = psDBGenerateCreateTableSQL(tableName, md);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-
-        return NULL;
-    }
-
-    status = psDBRunQuery(dbh, query);
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to create table.");
-    }
-
-    psFree(query);
-
-    return status;
-}
-
-bool psDBDropTable(psDB *dbh, const char *tableName)
-{
-    char            *query = NULL;
-    bool            status;
-
-    psStringAppend(&query, "DROP TABLE %s", tableName);
-
-    status = psDBRunQuery(dbh, query);
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to drop table.");
-    }
-
-    psFree(query);
-
-    return status;
-}
-
-psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, psU64 limit)
-{
-    MYSQL_RES       *result;            // complete db result set
-    MYSQL_ROW       row;                // single row of db result set
-    char            *query;             // SQL query
-    my_ulonglong    rowCount;           // number of rows in db result set
-    unsigned long   dataSize;           // size of field
-    unsigned int    fieldCount;         // number of fields in db result set
-    psArray         *column = NULL;     // return array
-    psPtr           data;               // copy of result field
-
-    query = psDBGenerateSelectRowSQL(tableName, col, NULL, limit);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-        return NULL;
-    }
-
-    if (!psDBRunQuery(dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
-        psFree(query);
-        return NULL;
-    }
-
-    psFree(query);
-
-    result = mysql_store_result(dbh->mysql);
-    if (!result) {
-        // no result set
-        fieldCount = mysql_field_count(dbh->mysql);
-
-        // if field count is zero the query returned no data.  If it's non-zero
-        // then something bad has happened.
-        if (fieldCount != 0) {
-            psError(PS_ERR_UNEXPECTED_NULL, true, "Query returned no data.  Error: %s", mysql_error(dbh->mysql));
-            return NULL;
-        }
-    }
-
-    rowCount = mysql_num_rows(result);
-
-    // pre-allocate enough elements to hold the complete result set
-    // then reset n to 0 so elements are added from the beginning of
-    // the array
-    column = psArrayAlloc(rowCount);
-    column->n = 0;
-
-    while ((row = mysql_fetch_row(result))) {
-        // get the first element of lengths array that is part of the
-        // result set
-        dataSize = *(mysql_fetch_lengths(result));
-
-        // represent NULL as an empty string
-        if (row[0] == NULL) {
-            data = psStringCopy("");
-        } else {
-            data = psAlloc(dataSize+1);
-            memcpy(data, row[0], dataSize);
-            ((char*)data)[dataSize] = '\0';
-        }
-
-        // add field to return array
-        psArrayAdd(column, 0, data);
-        psFree(data);
-    }
-
-    mysql_free_result(result);
-
-    return column;
-}
-
-// dest = assign to, source = source string psArray, conv = conversion function,
-// type = type to cast to, pType = psElemType
-#define PS_STR_ARRAY_TO_PTYPE(dest, source, conv, type, pType) \
-{ \
-    psPtr           myNaN; \
-    int             i; \
-    \
-    for (i = 0; i < source->n; i++) { \
-        if (strlen(source->data[i])) { \
-            dest[i] = (type)conv(source->data[i]); \
-        } else { \
-            myNaN = psDBGetPTypeNaN(pType); \
-            dest[i] = *(type *)myNaN; \
-            psFree(myNaN); \
-        } \
-    } \
-}
-
-psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType pType, const psU64 limit)
-{
-    psArray         *stringColumn;      // source psArray
-    psVector        *column;            // dest psVector
-
-    stringColumn = psDBSelectColumn(dbh, tableName, col, limit);
-    if (!stringColumn) {
-        // could be an error or the result set was just empty
-        return NULL;
-    }
-
-    column = psVectorAlloc(stringColumn->n, pType);
-
-    // conversion functions are a portability issue
-    switch (pType) {
-    case PS_TYPE_S8:
-        PS_STR_ARRAY_TO_PTYPE(column->data.S8, stringColumn, atoi, psS8, PS_TYPE_S8);
-        break;
-    case PS_TYPE_S16:
-        PS_STR_ARRAY_TO_PTYPE(column->data.S16, stringColumn, atoi, psS16, PS_TYPE_S16);
-        break;
-    case PS_TYPE_S32:
-        PS_STR_ARRAY_TO_PTYPE(column->data.S32, stringColumn, atoi, psS32, PS_TYPE_S32);
-        break;
-    case PS_TYPE_S64:
-        PS_STR_ARRAY_TO_PTYPE(column->data.S64, stringColumn, atoll, psS64, PS_TYPE_S64);
-        break;
-    case PS_TYPE_U8:
-        PS_STR_ARRAY_TO_PTYPE(column->data.U8, stringColumn, atoi, psU8, PS_TYPE_U8);
-        break;
-    case PS_TYPE_U16:
-        PS_STR_ARRAY_TO_PTYPE(column->data.U16, stringColumn, atoi, psU16, PS_TYPE_U16);
-        break;
-    case PS_TYPE_U32:
-        PS_STR_ARRAY_TO_PTYPE(column->data.U32, stringColumn, atoi, psU32, PS_TYPE_U32);
-        break;
-    case PS_TYPE_U64:
-        PS_STR_ARRAY_TO_PTYPE(column->data.U64, stringColumn, atoll, psU64, PS_TYPE_U64);
-        break;
-    case PS_TYPE_F32:
-        PS_STR_ARRAY_TO_PTYPE(column->data.F32, stringColumn, atof, psF32, PS_TYPE_F32);
-        break;
-    case PS_TYPE_F64:
-        PS_STR_ARRAY_TO_PTYPE(column->data.F64, stringColumn, atof, psF64, PS_TYPE_F64);
-        break;
-    case PS_TYPE_C32:
-        // this is a bogus SQL type
-        PS_STR_ARRAY_TO_PTYPE(column->data.C32, stringColumn, atof, psC32, PS_TYPE_C32);
-        break;
-    case PS_TYPE_C64:
-        // this is a bogus SQL type
-        PS_STR_ARRAY_TO_PTYPE(column->data.C64, stringColumn, atof, psC64, PS_TYPE_C64);
-        break;
-    case PS_TYPE_BOOL:
-        // valid for psVector?
-        break;
-    }
-
-    psFree(stringColumn);
-
-    return column;
-}
-
-psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, const psU64 limit)
-{
-    MYSQL_RES       *result;            // complete db result set
-    MYSQL_ROW       row;                // single row of db result set
-    MYSQL_FIELD     *field;             // field type info
-    char            *query;             // SQL query
-    my_ulonglong    rowCount;           // number of rows in db result set
-    unsigned int    fieldCount;         // number of fields in db result set
-    unsigned long   *fieldLength;       // field sizes
-    long            len;                // field length
-    psArray         *resultSet;         // return array
-    int             i;                  // field index
-    psMetadata      *md;                // a row
-    psU32           pType;              // psElemType of a field
-    psPtr           data;               // copy of result field
-
-    query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-
-        return NULL;
-    }
-
-    if (!psDBRunQuery(dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
-
-        psFree(query);
-
-        return NULL;
-    }
-
-    psFree(query);
-
-    result = mysql_store_result(dbh->mysql);
-    if (!result) {
-        // no result set
-        fieldCount = mysql_field_count(dbh->mysql);
-
-        // if field count is zero the query should have returned no data.  If
-        // it's non-zero then something bad has happened.
-        if (fieldCount != 0) {
-            psError(PS_ERR_UNEXPECTED_NULL, true, "Query returned no data.  Error: %s", mysql_error(dbh->mysql));
-
-            return NULL;
-        }
-    }
-
-    rowCount = mysql_num_rows(result);
-
-    // pre-allocate enough elements to hold the complete result set
-    // then reset n to 0 so elements are added from the beginning of
-    // the array
-    resultSet = psArrayAlloc(rowCount);
-    resultSet->n = 0;
-
-    field = mysql_fetch_fields(result);
-    fieldCount = mysql_num_fields(result);
-
-    while ((row = mysql_fetch_row(result))) {
-        // allocate new psMetadata to represent a row
-        md = psMetadataAlloc();
-
-        fieldLength = mysql_fetch_lengths(result);
-
-        for (i = 0; i < fieldCount; i++) {
-            // lookup MySQL column type
-            pType = psDBMySQLToPType(field[i].type, field[i].flags);
-
-            len = fieldLength[i];
-            if (len) {
-                data = psAlloc(len+1);
-                memcpy(data, row[i], len);
-                ((char*)data)[len] = '\0';
-            } else {
-                data = psDBGetPTypeNaN(pType);
-            }
-
-            // copy field data and convert NULLs to the appropriate NaN value
-            if (pType == PS_META_STR) {
-                psMetadataAddStr(md, 0, field[i].name, "", data);
-            } else if (pType == PS_META_S32) {
-                psMetadataAddS32(md, 0, field[i].name, "", atoll(data));
-            } else if (pType == PS_META_F32) {
-                psMetadataAddF32(md, 0, field[i].name, "", atof(data));
-            } else if (pType == PS_META_F64) {
-                psMetadataAddF64(md, 0, field[i].name, "", atof(data));
-            } else {
-                // XXX: assume binary string ...
-                psMetadataAddStr(md, 0, field[i].name, "", data);
-            }
-
-            psFree(data);
-        }
-
-        // add row to result set
-        psArrayAdd(resultSet, 0, md);
-        psFree(md);
-    }
-
-    mysql_free_result(result);
-
-    return resultSet;
-}
-
-bool psDBInsertOneRow(psDB *dbh, const char *tableName, psMetadata *row)
-{
-    psArray         *rowSet;            // psArray of row to insert
-
-    rowSet = psArrayAlloc(1);
-    rowSet->n = 0;
-    psArrayAdd(rowSet, 0, row);
-
-    if (!psDBInsertRows(dbh, tableName, rowSet)) {
-        psError(PS_ERR_UNKNOWN, false, "Insert failed.");
-
-        psFree(rowSet);
-
-        return false;
-    }
-
-    psFree(rowSet);
-
-    return true;
-}
-
-bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet)
-{
-    psMetadata      *row;               // row of data
-    char            *query;             // SQL query
-    MYSQL_STMT      *stmt;              // prepared db statement
-    MYSQL_BIND      *bind;              // field values to insert
-    unsigned long   paramCount;         // number of placeholders in query
-    psU64           j;                  // row index
-
-    // we are assuming that all rows in the set have an identical with reguard
-    // to field count and type
-    row = rowSet->data[0];
-
-    query = psDBGenerateInsertRowSQL(tableName, row);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-
-        return NULL;
-    }
-
-    stmt = mysql_stmt_init(dbh->mysql);
-    if (!stmt) {
-        psAbort(__func__, "mysql_stmt_init(), out of memory.");
-    }
-
-    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
-
-        mysql_stmt_close(stmt);
-        psFree(query);
-
-        return false;
-    }
-
-    psFree(query);
-
-    // how many place holders are in our query
-    paramCount = mysql_stmt_param_count(stmt);
-
-    // structure larger enough to hold one field of data per place holder
-    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
-
-    // loop over rows
-    for (j = 0; j < rowSet->n; j++) {
-        row = rowSet->data[j];
-
-        // reset bind for each row
-        memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
-
-        if (!psDBPackRow(bind, row, paramCount)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-        }
-
-        if (mysql_stmt_bind_param(stmt, bind)) {
-            psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-
-            return false;
-        }
-
-        if (mysql_stmt_execute(stmt)) {
-            psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
-                    mysql_stmt_error(stmt));
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-
-            return false;
-        }
-    } // end loop over rows
-
-    // point of no return
-    mysql_commit(dbh->mysql);
-
-    psFree(bind);
-    mysql_stmt_close(stmt);
-
-    return true;
-}
-
-psArray *psDBDumpRows(psDB *dbh, const char *tableName)
-{
-    return psDBSelectRows(dbh, tableName, NULL, 0);
-}
-
-psMetadata *psDBDumpCols(psDB *dbh, const char *tableName)
-{
-    MYSQL_RES       *result;
-    MYSQL_FIELD     *field;
-    unsigned int    fieldCount;
-    psMetadata      *table;
-    psU32           pType;
-    unsigned int    i;
-    psPtr           column;
-
-    // find column types
-    result = mysql_list_fields(dbh->mysql, tableName, NULL);
-    if (!result) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
-    }
-
-    field = mysql_fetch_fields(result);
-    fieldCount = mysql_num_fields(result);
-
-    table = psMetadataAlloc();
-
-    // fetch each column and load into psMetadata
-    for (i =0; i < fieldCount; i++) {
-        // find ptype of column
-        pType = psDBMySQLToPType(field[i].type, field[i].flags);
-        //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
-
-        // if the ptype is PS_TYPE_PTR assume that it's a string and fetch the
-        // column as an psArray of strings; otherwise fetch the column as a
-        // psVector.
-        if (pType == PS_META_STR) {
-            // PS_META_UNKNOWN -> PS_META_ARRAY ?
-            column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
-            psMetadataAddStr(table, 0, field[i].name, "", column);
-            psFree(column);
-        } else {
-            column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
-            if (pType == PS_META_S32) {
-                psMetadataAddS32(table, 0, field[i].name, "", (psS32)atoll(column));
-            } else if (pType == PS_META_F32) {
-                psMetadataAddF32(table, 0, field[i].name, "", (psF32)atof(column));
-            } else if (pType == PS_META_F64) {
-                psMetadataAddF64(table, 0, field[i].name, "", (psF64)atof(column));
-            }
-            psFree(column);
-        }
-    }
-
-    return table;
-}
-
-psS64 psDBUpdateRows(psDB *dbh, const char *tableName, psMetadata *where, psMetadata *values)
-{
-    char            *query;
-    MYSQL_STMT      *stmt;              // prepared db statement
-    unsigned long   paramCount;         // number of placeholders in query
-    MYSQL_BIND      *bind;              // field values to insert
-    my_ulonglong    rowsAffected;       // number of rows affected by query
-
-    query = psDBGenerateUpdateRowSQL(tableName, where, values);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-
-        return -1;
-    }
-
-    stmt = mysql_stmt_init(dbh->mysql);
-    if (!stmt) {
-        psAbort(__func__, "mysql_stmt_init(), out of memory.");
-    }
-
-    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
-
-        mysql_stmt_close(stmt);
-        psFree(query);
-
-        return -1;
-    }
-
-    psFree(query);
-
-    // how many place holders are in our query
-    paramCount = mysql_stmt_param_count(stmt);
-
-    // structure large enough to hold one field of data per place holder
-    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
-
-    // init bind
-    memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
-
-    if (!psDBPackRow(bind, values, paramCount)) {
-        psFree(bind);
-        mysql_stmt_close(stmt);
-
-        return -1;
-    }
-
-    if (mysql_stmt_bind_param(stmt, bind)) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
-
-        mysql_rollback(dbh->mysql);
-
-        psFree(bind);
-        mysql_stmt_close(stmt);
-
-        return -1;
-    }
-
-    if (mysql_stmt_execute(stmt)) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
-                mysql_stmt_error(stmt));
-
-        mysql_rollback(dbh->mysql);
-
-        psFree(bind);
-        mysql_stmt_close(stmt);
-
-        return -1;
-    }
-
-    psFree(bind);
-
-    // point of no return
-    mysql_commit(dbh->mysql);
-
-    rowsAffected = mysql_stmt_affected_rows(stmt);
-
-    mysql_stmt_close(stmt);
-
-    return rowsAffected;
-}
-
-psS64 psDBDeleteRows(psDB *dbh, const char *tableName, psMetadata *where)
-{
-    char            *query;
-
-    query = psDBGenerateDeleteRowSQL(tableName, where);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-
-        return -1;
-    }
-
-    if (!psDBRunQuery(dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "Delete failed.");
-
-        mysql_rollback(dbh->mysql);
-
-        psFree(query);
-
-        return -1;
-    }
-
-    psFree(query);
-
-    if (!where) {
-        // we truncated the table so mysql_affected_rows() won't work
-        return 1;
-    }
-
-    // point of no return
-    mysql_commit(dbh->mysql);
-
-    return (psS64)mysql_affected_rows(dbh->mysql);
-}
-
-// database utility functions
-/*****************************************************************************/
-
-static bool psDBRunQuery(psDB *dbh, const char *query)
-{
-    if (mysql_real_query(dbh->mysql, query, (unsigned long)strlen(query)) !=0) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to execute query.  Error: %s\n", mysql_error(dbh->mysql));
-
-        return false;
-    }
-
-    return true;
-}
-
-static inline bool psDBPackRow(MYSQL_BIND *bind, psMetadata *values, psU32 paramCount)
-{
-    psListIterator  *cursor;            // row iterator
-    psMetadataItem  *item;              // field in row
-    mysqlType       *mType;             // type tmp variable
-    static bool     isNull = true;      // used in a MYSQL_BIND to indicate NULL,
-    // this will be used outside of this func
-    psU32           i;                  // field index
-
-    // check size of values == paramCount ?
-
-    cursor = psListIteratorAlloc(values->list, 0, false);
-
-    // loop over fields
-    i = 0;
-    while ((item = psListGetAndIncrement(cursor))) {
-        // lookup pType -> mysql type
-        mType = psDBPTypeToMySQL(item->type);
-
-        bind[i].buffer_type = mType->type;
-        bind[i].is_unsigned = mType->isUnsigned;
-
-        psFree(mType);
-
-        // input data length is determined by the MYSQL_TYPE_* unless it's a string
-        if (item->type == PS_TYPE_S32) {
-            bind[i].length  = 0;
-            bind[i].buffer  = &item->data.S32;
-            bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.S32)
-                              ? (my_bool *)&isNull
-                              : NULL;
-        } else if (item->type == PS_TYPE_F32) {
-            bind[i].length  = 0;
-            bind[i].buffer  = &item->data.F32;
-            bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F32)
-                              ? (my_bool *)&isNull
-                              : NULL;
-        } else if (item->type == PS_TYPE_F64) {
-            bind[i].length  = 0;
-            bind[i].buffer  = &item->data.F64;
-            bind[i].is_null = psDBIsPTypeNaN(item->type, &item->data.F64)
-                              ? (my_bool *)&isNull
-                              : NULL;
-            // convert NaNs to NULL and set the buffer_length for strings
-            //} else if ((item->type == PS_META_STR) && (item->pType == PS_TYPE_PTR)) {
-        } else if ((item->type == PS_META_STR)         || (item->type == PS_META_VEC)    ||
-                   (item->type == PS_META_IMG)         || (item->type == PS_META_HASH)   ||
-                   (item->type == PS_META_LOOKUPTABLE) || (item->type == PS_META_JPEG)   ||
-                   (item->type == PS_META_PNG)         || (item->type == PS_META_ASTROM) ||
-                   (item->type == PS_META_UNKNOWN)) {
-
-            bind[i].buffer_length = (unsigned long)strlen((char *)item->data.V);
-            bind[i].length  = &bind[i].buffer_length;
-            bind[i].buffer  = item->data.V;
-            bind[i].is_null = *(char *)item->data.V == '\0'
-                              ? (my_bool *)&isNull
-                              : NULL;
-        } else {
-            psError(PS_ERR_BAD_PARAMETER_TYPE , true,
-                    "FIXME: Only type of PS_TYPE_S32, PS_TYPE_F32, PS_TYPE_F64, "
-                    "and PS_TYPE_PTR are supported.");
-
-            psFree(cursor);
-
-            return false;
-        }
-
-        // increment field index
-        i++;
-    }
-
-    psFree(cursor);
-
-    return true;
-}
-
-
-// SQL generation functions
-/*****************************************************************************/
-
-static char *psDBGenerateCreateTableSQL(const char *tableName, psMetadata *table)
-{
-    char            *query = NULL;      // complete query
-    psMetadataItem  *item;              // column description
-    psListIterator  *cursor;            // column iterator
-    char            *colType;           // type lookup table
-
-    if (!table) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, "table param may not be null.");
-
-        return NULL;
-    }
-
-    psStringAppend(&query, "CREATE TABLE %s (", tableName);
-
-    cursor = psListIteratorAlloc(table->list, 0, false);
-
-    // find column name and type
-    while ((item = psListGetAndIncrement(cursor))) {
-        if ((item->type == PS_META_S32) || (item->type == PS_META_F32) || (item->type == PS_META_F64) ||
-                (item->type == PS_TYPE_S32) || (item->type == PS_TYPE_F32) || (item->type == PS_TYPE_F64)) {
-            // + column name + _ + column type
-            colType = psDBPTypeToSQL(item->type);
-            psStringAppend(&query, "%s %s", item->name, colType);
-            psFree(colType);
-        } else if ((item->type == PS_META_STR)         || (item->type == PS_META_VEC)    ||
-                   (item->type == PS_META_IMG)         || (item->type == PS_META_HASH)   ||
-                   (item->type == PS_META_LOOKUPTABLE) || (item->type == PS_META_JPEG)   ||
-                   (item->type == PS_META_PNG)         || (item->type == PS_META_ASTROM) ||
-                   (item->type == PS_META_UNKNOWN)) {
-            // + column name + _ + varchar( + length + )
-            psStringAppend(&query, "%s VARCHAR(%s)", item->name, item->data.V);
-        } else {
-            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
-                    "FIXME: Only type of PS_META_S32, PS_META_F32, PS_META_F64, "
-                    "and PS_META_* pointer types are supported, (not %d).", item->type);
-
-            psFree(query);
-            psFree(cursor);
-
-            return NULL;
-        }
-
-        // add a , after every column declaration except the last one
-        if (!cursor->offEnd) {
-            psStringAppend(&query, ", ");
-        }
-    }
-
-    psListIteratorSet(cursor, 0);
-
-    // find database indexes
-    while ((item = psListGetAndIncrement(cursor))) {
-        if ((strncmp(item->comment, "Primary Key", strlen("Primary Key"))) == 0) {
-            psStringAppend(&query, ", PRIMARY KEY(%s)", item->name);
-        } else if ((strncmp(item->comment, "Key", strlen("Key"))) == 0) {
-            psStringAppend(&query, ", KEY(%s)", item->name);
-        }
-    }
-
-    psFree(cursor);
-
-    // end column types + table type
-    psStringAppend(&query, ") ENGINE=innodb");
-
-    return query;
-}
-
-static char *psDBGenerateSelectRowSQL(const char *tableName, const char *col, psMetadata *where, const psU64 limit)
-{
-    char            *query = NULL;
-    char            *whereSQL;
-    char            *limitString;
-
-    // select all columns if col is NULL
-    if (col) {
-        psStringAppend(&query, "SELECT %s FROM %s", col, tableName);
-    } else {
-        psStringAppend(&query, "SELECT * FROM %s", tableName);
-    }
-
-    // select all rows if where is NULL
-    if (where) {
-        whereSQL = psDBGenerateWhereSQL(where);
-        if (!whereSQL) {
-            psError(PS_ERR_UNEXPECTED_NULL, false, "SQL substring generation failed.");
-
-            psFree(query);
-
-            return NULL;
-        }
-        psStringAppend(&query, " %s", whereSQL);
-        psFree(whereSQL);
-    }
-
-    // treat limit == 0 as "no limit"
-    if (limit) {
-        limitString = psDBIntToString(limit);
-        psStringAppend(&query, " LIMIT %s", limitString);
-        psFree(limitString);
-    }
-
-    return query;
-}
-
-static char *psDBGenerateInsertRowSQL(const char *tableName, psMetadata *row)
-{
-    char            *query = NULL;
-    psListIterator  *cursor;
-    psMetadataItem  *item;
-
-    psStringAppend(&query, "INSERT INTO %s (", tableName);
-
-    cursor = psListIteratorAlloc(row->list, 0, false);
-
-    // get field names
-    while ((item = psListGetAndIncrement(cursor))) {
-        psStringAppend(&query, item->name);
-
-        // + , + _ between every field name
-        if (!cursor->offEnd) {
-            psStringAppend(&query, ", ");
-        }
-    }
-
-    // end of field names
-    psStringAppend(&query, ") VALUES (");
-
-    psListIteratorSet(cursor, 0);
-
-    // create value place holders
-    while ((item = psListGetAndIncrement(cursor))) {
-        psStringAppend(&query, "?");
-
-        // + ", " between every place holder
-        if (!cursor->offEnd) {
-            psStringAppend(&query, ", ");
-        }
-    }
-
-    psFree(cursor);
-
-    // end of values
-    psStringAppend(&query, ")");
-
-    return query;
-}
-
-static char *psDBGenerateUpdateRowSQL(const char *tableName, psMetadata *where, psMetadata *values)
-{
-    char            *query = NULL;
-    char            *setSQL;
-    char            *whereSQL;
-
-    if ((!values) || (!where)) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, "values and where params may not be NULL.");
-
-        return NULL;
-    }
-
-    setSQL = psDBGenerateSetSQL(values);
-    if (!setSQL) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "SQL substring generation failed.");
-
-        return NULL;
-    }
-
-    whereSQL = psDBGenerateWhereSQL(where);
-    if (!whereSQL) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "SQL substring generation failed.");
-
-        return NULL;
-    }
-
-    psStringAppend(&query, "UPDATE %s %s %s", tableName, setSQL, whereSQL);
-    psFree(setSQL);
-    psFree(whereSQL);
-
-    return query;
-}
-
-static char *psDBGenerateDeleteRowSQL(const char *tableName, psMetadata *where)
-{
-    char            *query = NULL;
-    char            *whereSQL;
-
-    // delete all rows if where is NULL
-    if (!where) {
-        psStringAppend(&query, "TRUNCATE TABLE %s", tableName);
-
-        return query;
-    }
-
-    whereSQL = psDBGenerateWhereSQL(where);
-    if (!whereSQL) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "SQL substring generation failed.");
-
-        return NULL;
-    }
-
-    psStringAppend(&query, "DELETE FROM %s %s", tableName, whereSQL);
-    psFree(whereSQL);
-
-    return query;
-}
-
-static char *psDBGenerateWhereSQL(psMetadata *where)
-{
-    char            *query = NULL;
-    psListIterator  *cursor;
-    psMetadataItem  *item;
-
-    if (!where) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, "where param may not be NULL.");
-
-        return NULL;
-    }
-
-    query = psStringCopy("WHERE ");
-
-    cursor = psListIteratorAlloc(where->list, 0, false);
-
-    // find column name and match pattern
-    while ((item = psListGetAndIncrement(cursor))) {
-        // item->data must be a string
-        if ((item->type == PS_META_S32) || (item->type == PS_TYPE_S32)) {
-            psStringAppend(&query, "%s=%d", item->name, (int)(item->data.S32));
-        } else if ((item->type == PS_META_F32) || (item->type == PS_TYPE_F32)) {
-            psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F32));
-        } else if ((item->type == PS_META_F64) || (item->type == PS_TYPE_F64)) {
-            psStringAppend(&query, "%s=%g", item->name, (double)(item->data.F64));
-        } else if (item->type == PS_META_STR) {
-            // + column name + _ + like + _ + ' + value + '
-            if (*(char *)item->data.V == '\0') {
-                psStringAppend(&query, "%s IS NULL", item->name);
-            } else {
-                // XXX ASC NOTE: we should have a better match for
-                // char & varchar columns than this.  LIKE is OK for
-                // very large TEXT columns that really shouldn't be
-                // used in a where clause...
-                psStringAppend(&query, "%s LIKE '%s'", item->name, item->data.V);
-            }
-        } else {
-            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
-                    "Only types PS_META_S32, PS_META_F32, PS_META_F64, PS_META_STR is supported");
-
-            psFree(cursor);
-            psFree(query);
-
-            return NULL;
-        }
-
-        // + " and " after every column declaration except the last one
-        if (!cursor->offEnd) {
-            psStringAppend(&query, " AND ");
-        }
-    }
-
-    psFree(cursor);
-
-    return query;
-}
-
-static char *psDBGenerateSetSQL(psMetadata *set
-                               )
-{
-    char            *query = NULL;
-    psListIterator  *cursor;
-    psMetadataItem  *item;
-
-    if (!set
-       ) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true, "set param may not be NULL.");
-
-        return NULL;
-    }
-
-    query = psStringCopy("SET ");
-
-    cursor = psListIteratorAlloc(set
-                                 ->list, 0, false);
-
-    // find column name
-    while ((item = psListGetAndIncrement(cursor))) {
-        // + column name + _ + = + _ + ?
-        psStringAppend(&query, "%s = ?", item->name);
-
-        // + ", " after every column declaration except the last one
-        if (!cursor->offEnd) {
-            psStringAppend(&query, ",  ");
-        }
-    }
-
-    psFree(cursor);
-
-    return query;
-}
-
-
-// lookup table functions
-/*****************************************************************************/
-
-static psElemType psDBMySQLToPType(enum enum_field_types type, unsigned int flags)
-{
-    psHash          *mysqlToSQLTable;   // type lookup table
-    psHash          *sqlToPSTable;      // type lookup table
-    char            *key;               // hash tmp value
-    char            *value;             // hash tmp value
-    char            *sqlType;           // copy of lookup table result
-    psU32           pType;              // psElemType of a field
-
-    mysqlToSQLTable = psDBGetMySQLToSQLTable();
-
-    // lookup MySQL column type
-    key     = psDBIntToString((psU64)type);
-    sqlType = psHashLookup(mysqlToSQLTable, key);
-    psFree(key);
-    psFree(mysqlToSQLTable);
-
-    if (!sqlType) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
-        return -1;
-    }
-
-    // MySQL column types can not be directly translated to PS
-    // types as the the mysql types do not tell you if the value is
-    // signed or unsigned.  The result is this ugly conversion from
-    // mysql -> ascii -> ptype
-    if (flags & UNSIGNED_FLAG) {
-        psStringPrepend(&sqlType, "UNSIGNED ");
-    }
-
-    //psLogMsg( __func__, PS_LOG_INFO, "sqlType=[%s]\n", sqlType );
-
-    // convert MySQL type to PS type
-    sqlToPSTable = psDBGetSQLToPTypeTable();
-    value = psHashLookup(sqlToPSTable, sqlType);
-    psFree(sqlToPSTable);
-
-    if (!value) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
-
-        return -1;
-    }
-
-    pType = (psU32)atol(value);
-
-    return pType;
-}
-
-static char *psDBPTypeToSQL(psElemType pType)
-{
-    psHash          *pTypeToSQLTable;   // type lookup table
-    char            *key;               // hash tmp value
-    char            *sqlType;             // hash tmp value
-
-    pTypeToSQLTable = psDBGetPTypeToSQLTable();
-
-    key = psDBIntToString((psU64)pType);
-    sqlType = psHashLookup(pTypeToSQLTable, key);
-    psFree(key);
-    psFree(pTypeToSQLTable);
-
-    if (!sqlType) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
-
-        return NULL;
-    }
-
-    psMemIncrRefCounter(sqlType);
-
-    return sqlType;
-}
-
-static mysqlType *psDBPTypeToMySQL(psElemType pType)
-{
-    psHash          *pTypeToMySQLTable; // type lookup table
-    char            *key;               // hash tmp value
-    mysqlType       *mType;             // mysqlType struct to return
-
-    pTypeToMySQLTable = psDBGetPTypeToMySQLTable();
-
-    key = psDBIntToString((psU64)pType);
-    mType = psHashLookup(pTypeToMySQLTable, key);
-    psFree(key);
-    psFree(pTypeToMySQLTable);
-
-    if (!mType) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "type lookup failed.");
-
-        return NULL;
-    }
-
-    psMemIncrRefCounter(mType);
-
-    return mType;
-}
-
-static psHash *psDBGetPTypeToSQLTable(void)
-{
-    static psHash   *lookupTable = NULL;
-
-    if (!lookupTable) {
-        lookupTable = psHashAlloc(14);
-
-        // no support for CHAR, TEXT or GLOB
-        psDBAddToLookupTable(lookupTable, PS_TYPE_S8,  "TINYINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_S16, "SMALLINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_S32, "INT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_S64, "BIGINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_U8,  "UNSIGNED TINYINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_U16, "UNSIGNED SMALLINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_U32, "UNSIGNED INT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_U64, "UNSIGNED BIGINT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_F32, "FLOAT");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_F64, "DOUBLE");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_C32, "PS_TYPE_C32 is not supported");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_C64, "PS_TYPE_C64 is not supported");
-        psDBAddToLookupTable(lookupTable, PS_TYPE_BOOL,"BOOLEAN");
-        psDBAddToLookupTable(lookupTable, PS_META_STR, "BLOB");
-    }
-
-    // simulate true ref counting
-    psMemIncrRefCounter(lookupTable);
-
-    return lookupTable;
-}
-
-static void psDBPTypeToSQLTableCleanup(void)
-{
-    psHash          *lookupTable;
-
-    lookupTable = psDBGetPTypeToSQLTable();
-
-    psMemDecrRefCounter(lookupTable);
-    psFree(lookupTable);
-}
-
-static psHash *psDBGetSQLToPTypeTable(void)
-{
-    static psHash   *lookupTable = NULL;
-    psHash          *psToSQLTable;
-    psList          *list;
-    psListIterator  *cursor;
-    char            *key;
-    char            *value;
-
-    if (!lookupTable) {
-        // invert the PSToSQL table
-        psToSQLTable = psDBGetPTypeToSQLTable();
-        lookupTable = psHashAlloc(psToSQLTable->nbucket);
-
-        list = psHashKeyList(psToSQLTable);
-        cursor = psListIteratorAlloc(list, 0, false);
-
-        while ((key = psListGetAndIncrement(cursor))) {
-            value = psHashLookup(psToSQLTable, key);
-            if (!strcmp(value, "BLOB")) {
-                continue; // ignore reverse BLOB mapping, fill in below
-            }
-            // switch key and value
-            psHashAdd(lookupTable, value, key);
-        }
-
-        value = psDBIntToString((psU64)PS_META_STR);
-        psHashAdd(lookupTable, "VARCHAR", value);
-        psHashAdd(lookupTable, "BLOB",    value);
-        psHashAdd(lookupTable, "TEXT",    value);
-        psFree(value);
-
-        // DECIMAL does not exist in the pType to SQL table
-        value = psDBIntToString(0);
-        psHashAdd(lookupTable, "DECIMAL", value);
-        psFree(value);
-
-        psFree(cursor);
-        psFree(list);
-        psFree(psToSQLTable);
-    }
-
-    // simulate true ref counting
-    psMemIncrRefCounter(lookupTable);
-
-    return lookupTable;
-}
-
-static void psDBSQLToPTypeTableCleanup(void)
-{
-    psHash          *lookupTable;
-
-    lookupTable = psDBGetSQLToPTypeTable();
-
-    psMemDecrRefCounter(lookupTable);
-    psFree(lookupTable);
-}
-
-static psHash *psDBGetMySQLToSQLTable(void)
-{
-    static psHash   *lookupTable = NULL;
-
-    if (!lookupTable) {
-        lookupTable = psHashAlloc(20);
-
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_TINY,      "TINYINT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_SHORT,     "SMALLINT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_LONG,      "INT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_INT24,     "MEDIUMINT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_LONGLONG,  "BIGINT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_DECIMAL,   "DECIMAL");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_FLOAT,     "FLOAT");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_DOUBLE,    "DOUBLE");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_TIMESTAMP, "TIMESTAMP");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_DATE,      "DATE");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_TIME,      "TIME");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_DATETIME,  "DATETIME");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_YEAR,      "YEAR");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_STRING,    "CHAR");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_VAR_STRING,"VARCHAR");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_BLOB,      "BLOB");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_SET,       "SET");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_ENUM,      "ENUM");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_NULL,      "NULL-type");
-        psDBAddToLookupTable(lookupTable, FIELD_TYPE_CHAR,      "TINYINT");
-    }
-
-    // simulate true ref counting
-    psMemIncrRefCounter(lookupTable);
-
-    return lookupTable;
-}
-
-static void psDBMySQLToSQLTableCleanup(void)
-{
-    psHash          *lookupTable;
-
-    lookupTable = psDBGetMySQLToSQLTable();
-
-    psMemDecrRefCounter(lookupTable);
-    psFree(lookupTable);
-}
-
-static psHash *psDBGetPTypeToMySQLTable(void)
-{
-    static psHash   *lookupTable = NULL;
-
-    if (!lookupTable) {
-        lookupTable = psHashAlloc(14);
-
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_S8,     psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_S16,    psDBMySQLTypeAlloc(MYSQL_TYPE_SHORT,      false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_S32,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONG,       false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_S64,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONGLONG,   false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_U8,     psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       true));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_U16,    psDBMySQLTypeAlloc(MYSQL_TYPE_SHORT,      true));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_U32,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONG,       true));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_U64,    psDBMySQLTypeAlloc(MYSQL_TYPE_LONGLONG,   true));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_F32,    psDBMySQLTypeAlloc(MYSQL_TYPE_FLOAT,      false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_F64,    psDBMySQLTypeAlloc(MYSQL_TYPE_DOUBLE,     false));
-        // bogus type
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_C32,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        // bogus type
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_C64,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_TYPE_BOOL,   psDBMySQLTypeAlloc(MYSQL_TYPE_TINY,       true));
-        // XXX: removed PS_TYPE_PTR, can this be removed too?
-        // psDBAddVoidToLookupTable(lookupTable, PS_TYPE_PTR,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-
-        psDBAddVoidToLookupTable(lookupTable, PS_META_STR,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_VEC,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_IMG,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_HASH,   psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_LOOKUPTABLE,
-                                 psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_JPEG,   psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_PNG,    psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_ASTROM, psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-        psDBAddVoidToLookupTable(lookupTable, PS_META_UNKNOWN,psDBMySQLTypeAlloc(MYSQL_TYPE_VAR_STRING, false));
-    }
-
-    // simulate true ref counting
-    psMemIncrRefCounter(lookupTable);
-
-    return lookupTable;
-}
-
-static void psDBPTypeToMySQLTableCleanup(void)
-{
-    psHash          *lookupTable;
-
-    lookupTable = psDBGetPTypeToMySQLTable();
-
-    psMemDecrRefCounter(lookupTable);
-    psFree(lookupTable);
-}
-
-static psPtr psDBMySQLTypeAlloc(enum enum_field_types type, bool isUnsigned)
-{
-    mysqlType       *mType;
-
-    mType = psAlloc(sizeof(mysqlType));
-    mType->type       = type;
-    mType->isUnsigned = isUnsigned;
-
-    return mType;
-}
-
-static void psDBAddToLookupTable(psHash *lookupTable, psU32 type, const char *string)
-{
-    char            *key;
-    char            *value;
-
-    key = psDBIntToString((psU64)type);
-    value = psStringCopy(string);
-
-    psHashAdd(lookupTable, key, value);
-
-    psFree(key);
-    psFree(value);
-}
-
-static void psDBAddVoidToLookupTable(psHash *lookupTable, psU32 type, psPtr value)
-{
-    char            *key;
-
-    key = psDBIntToString((psU64)type);
-
-    psHashAdd(lookupTable, key, value);
-
-    // destructive of value parameter
-    psFree(value);
-    psFree(key);
-}
-
-
-// pType utility functions
-/*****************************************************************************/
-
-#define PS_NAN_ALLOC(dest, type, nan) \
-dest = psAlloc(sizeof(type)); \
-*(type *)dest = nan;
-
-static psPtr psDBGetPTypeNaN(psElemType pType)
-{
-    psPtr           myNaN;
-
-    switch (pType) {
-    case PS_TYPE_S8:
-        PS_NAN_ALLOC(myNaN, psS8, PS_MAX_S8);
-        break;
-    case PS_TYPE_S16:
-        PS_NAN_ALLOC(myNaN, psS16, PS_MAX_S16);
-        break;
-    case PS_TYPE_S32:
-        PS_NAN_ALLOC(myNaN, psS32, PS_MAX_S32);
-        break;
-    case PS_TYPE_S64:
-        PS_NAN_ALLOC(myNaN, psS64, PS_MAX_S64);
-        break;
-    case PS_TYPE_U8:
-        PS_NAN_ALLOC(myNaN, psU8, PS_MAX_U8);
-        break;
-    case PS_TYPE_U16:
-        PS_NAN_ALLOC(myNaN, psU16, PS_MAX_U16);
-        break;
-    case PS_TYPE_U32:
-        PS_NAN_ALLOC(myNaN, psU32, PS_MAX_U32);
-        break;
-    case PS_TYPE_U64:
-        PS_NAN_ALLOC(myNaN, psU64, PS_MAX_U64);
-        break;
-    case PS_TYPE_F32:
-        PS_NAN_ALLOC(myNaN, psF32, NAN);
-        break;
-    case PS_TYPE_F64:
-        PS_NAN_ALLOC(myNaN, psF64, NAN);
-        break;
-    case PS_TYPE_C32:
-        // this is a bogus SQL type
-        PS_NAN_ALLOC(myNaN, psC32, NAN);
-        break;
-    case PS_TYPE_C64:
-        // this is a bogus SQL type
-        PS_NAN_ALLOC(myNaN, psC64, NAN);
-        break;
-    case PS_TYPE_BOOL:
-        // what is NaN for a bool?
-        break;
-    }
-
-    return myNaN;
-}
-
-#define PS_IS_NAN(type, data, nan) *(type *)data == nan
-
-static bool psDBIsPTypeNaN(psElemType pType, psPtr data)
-{
-    bool    isNaN;
-
-    switch (pType) {
-    case PS_TYPE_S8:
-        isNaN = PS_IS_NAN(psS8, data, PS_MAX_S8);
-        break;
-    case PS_TYPE_S16:
-        isNaN = PS_IS_NAN(psS16, data, PS_MAX_S16);
-        break;
-    case PS_TYPE_S32:
-        isNaN = PS_IS_NAN(psS32, data, PS_MAX_S32);
-        break;
-    case PS_TYPE_S64:
-        isNaN = PS_IS_NAN(psS64, data, PS_MAX_S64);
-        break;
-    case PS_TYPE_U8:
-        isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8);
-        break;
-    case PS_TYPE_U16:
-        isNaN = PS_IS_NAN(psU16, data, PS_MAX_U16);
-        break;
-    case PS_TYPE_U32:
-        isNaN = PS_IS_NAN(psU32, data, PS_MAX_U32);
-        break;
-    case PS_TYPE_U64:
-        isNaN = PS_IS_NAN(psU64, data, PS_MAX_U64);
-        break;
-    case PS_TYPE_F32:
-        isNaN = PS_IS_NAN(psF32, data, NAN);
-        break;
-    case PS_TYPE_F64:
-        isNaN = PS_IS_NAN(psF64, data, NAN);
-        break;
-    case PS_TYPE_C32:
-        // this is a bogus SQL type
-        isNaN = PS_IS_NAN(psC32, data, NAN);
-        break;
-    case PS_TYPE_C64:
-        // this is a bogus SQL type
-        isNaN = PS_IS_NAN(psC64, data, NAN);
-        break;
-    case PS_TYPE_BOOL:
-        // what is NaN for a bool?
-        break;
-    }
-
-    return isNaN;
-}
-
-
-// string utility functions
-/*****************************************************************************/
-
-static char *psDBIntToString(psU64 n)
-{
-    char            *string;
-    size_t          length;
-
-    // length of string + \0
-    // if n is 0, length is 1 char + \0
-    length = n ? (size_t)log10((double)n) + 1
-             : 2;
-    string = psAlloc(length);
-    sprintf(string, "%li", (long int)n);
-
-    return string;
-}
-
-static ssize_t psStringAppend(char **dest, const char *format, ...)
-{
-    va_list         args;
-    size_t          length;             // complete string length (sans \0)
-    size_t          oldLength;          // original string length (sans \0)
-    ssize_t         tailLength;         // length of string to append
-
-    if (!*dest) {
-        *dest = psStringCopy("");
-        oldLength = 0;
-    } else {
-        // size of existing string
-        oldLength = strlen(*dest);
-    }
-
-    // find the size of the string to append
-    va_start(args, format);
-    // C99 guarentees vsnprintf() to work as expected with size = 0
-    tailLength = vsnprintf(*dest, 0, format, args);
-    va_end(args);
-
-    // if the new tail is zero length, return the length of the old string.  if
-    // it's a format error, return the error code.
-    if (tailLength < 1) {
-        return tailLength == 0 ? oldLength : tailLength;
-    }
-
-    // new string length (sans \0)
-    length = oldLength + tailLength;
-
-    // realloc string to string + tail + \0
-    *dest = psRealloc(*dest, length + 1);
-
-    // append tail + \0
-    va_start(args, format);
-    vsnprintf(*dest + oldLength, tailLength + 1, format, args);
-    va_end(args);
-
-    return length;
-}
-
-static ssize_t psStringPrepend(char **dest, const char *format, ...)
-{
-    va_list         args;
-    size_t          length;             // complete string length (sans \0)
-    ssize_t         headLength;         // length of string to prepend
-    char            *oldDest;           // copy of original string
-
-    if (!*dest) {
-        // makes the string backup and concatination pointless
-        *dest = psStringCopy("");
-        length = 0;
-    } else {
-        // size of existing string
-        length = strlen(*dest);
-    }
-
-    // find the size of the string to prepend
-    va_start(args, format);
-    // C99 guarentees vsnprintf() to work as expected with size = 0
-    headLength = vsnprintf(*dest, 0, format, args);
-    va_end(args);
-
-    // if the new head is zero length, return the length of the old string.  if
-    // it's a format error, return the error code.
-    if (headLength < 1) {
-        return headLength == 0 ? length : headLength;
-    }
-
-    // backup original string
-    oldDest = psStringCopy(*dest);
-
-    // new string length (sans \0)
-    length += headLength;
-
-    // realloc string to head + string + \0
-    *dest = psRealloc(*dest, length + 1);
-
-    // copy the new head to the beginning of string
-    va_start(args, format);
-    vsnprintf(*dest, length + 1, format, args);
-    va_end(args);
-
-    // append the original string
-    strncat(*dest, oldDest, length + 1);
-
-    psFree(oldDest);
-
-    return length;
-}
-
-#endif // BUILD_PSDB
Index: trunk/psLib/src/astronomy/psDB.h
===================================================================
--- trunk/psLib/src/astronomy/psDB.h	(revision 3690)
+++ 	(revision )
@@ -1,267 +1,0 @@
-/** @file  psDB.h
- *
- *  @brief database types and functions
- *
- *  This file defines the abstract database type and functions that
- *  perform basic database operations.
- *
- *  @ingroup DataBase
- *
- *  @author Joshua Hoblitt
- *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-03-31 23:01:46 $
- *
- *  Copyright 2005 Joshua Hoblitt, University of Hawaii
- */
-
-#ifndef PS_DB_H
-#define PS_DB_H 1
-
-#ifdef BUILD_PSDB
-
-#include "psType.h"
-#include "psMetadata.h"
-
-/// @addtogroup DataBase
-/// @{
-
-/** Database handle
- *
- *  An opaque object representing a database connection.
- *
- */
-typedef struct
-{
-    void* mysql;   ///< MySQL database handle
-}
-psDB;
-
-/** Opens a new database connection
- *
- *  @return A new psDB object if the database connection is successful or NULL on
- *  failure.
- */
-psDB *psDBInit(
-    const char *host,                   ///< Database server hostname
-    const char *user,                   ///< Database username
-    const char *passwd,                 ///< Database password
-    const char *dbname                  ///< Database namespace
-);
-
-/** Closes a database connection
- */
-void psDBCleanup(
-    psDB *dbh                           ///< Database handle
-);
-
-/** Creates a new database namespace
- *
- * @return true on success
- */
-bool psDBCreate(
-    psDB *dbh,                          ///< Database handle
-    const char *dbname                  ///< New database namespace
-);
-
-/** Changes the current database namespace
- *
- * @return true on success
- */
-bool psDBChange(
-    psDB *dbh,                          ///< Database handle
-    const char *dbname                  ///< Database namespace
-);
-
-/** Drops a database namespace
- *
- * @return true on success
- */
-bool psDBDrop(
-    psDB *dbh,                          ///< Database handle
-    const char *dbname                  ///< Database namespace
-);
-
-/** Creates a new database table
- *
- * This function generates and executes the SQL needed to create a table named
- * "tableName", with the column names and data types as described in "md".  Each
- * data item in the psMetadata collection represents a single table field.  The
- * name of the field is given by the name of the psMetadataItem and the data
- * type is give by the psMetadataItem.type and psMetadataItem.ptype entries.  A
- * lookup table should be used to convert from PSLib types into MySQL
- * compatible SQL data types.  For example, a PS_META_STR would map to an SQL99
- * varchar.  If the value of type is PS_META_STR then the psMetadataItem.data
- * element is set to a string with the length for the field written as a text
- * string.  The value of the psMetadataItem.data element is unused for the
- * PS_META_PRIMITIVE types.  Other psMetadata types beyond PS_META_STR and
- * PS_META_PRIMITIVE are not allowed in a table definition.  
- *
- * Database indexes can be specified setting the "comment" field to "Primary
- * Key" or "Key".  Comments are otherwise ignored.
- *
- * @return true on success
- */
-bool psDBCreateTable(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    psMetadata *md                      ///< Column names, types, and indexes
-);
-
-/** Deletes a database table
- *
- * @return true on success
-*/
-bool psDBDropTable(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName               ///< Table name
-);
-
-/** Selects a column from a table
- *
- * This function generates and executes the SQL needed to select an entire
- * column from a table or up to "limit" rows from it.  If "limit" is 0, the
- * entire range is returned.
- *
- * @return A psArray of strings or NULL on failure
- */
-psArray *psDBSelectColumn(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    const char *col,                    ///< Column name
-    const psU64 limit                   ///< Maximum number of elements to return
-);
-
-/** Selects a column from a table and casts it to a given type
- *
- * This function generates and executes the SQL needed to select an entire
- * column from a table or up to "limit" rows from it.  If "limit" is 0, the
- * entire range is returned.  The data in the column is cast to to "pType".
- *
- * @return A psVector or NULL on failure
- */
-psVector *psDBSelectColumnNum(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    const char *col,                    ///< Column name
-    psElemType pType,                   ///< Resulting psVector type
-    const psU64 limit                   ///< Maximum number of elements to return
-);
-
-/** Selects a set of rows from a table
- *
- * This function returns rows from the specified table which match the
- * restrictions given by "where".  The restrictions are specified as field /
- * value pairs.  The psMetadata collection "where" must consist of valid
- * database fields.  The selected rows are returned as a psArray of psMetadata
- * values, one per row.
- *
- * Currently, the "where" specification only supports the PS_META_STR type.
- * The string value can be a SQL match pattern, e.g. "%foo%", or an empty
- * string, e.g. "", to match NULL field values.
- *
- * @return A psArray of psMetadata or NULL on failure
- */
-psArray *psDBSelectRows(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    psMetadata *where,                  ///< Row match criteria
-    const psU64 limit                   ///< Maximum number of elements to return
-);
-
-/** Insert a single row into a table
- *
- * This function inserts the data from "row" into "tableName".
- *
- * The "row" specification uses the psMetadataItem name as the column name.
- * The field values may be specified in any order.  psMetadata types beyond
- * PS_META_STR and PS_META_PRIMITIVE are not supported.  If fields are
- * specified in "row" that do not exist in "tableName", the insert will fail.
- *
- * @return true on success
- */
-bool psDBInsertOneRow(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    psMetadata *row                     ///< Row description
-);
-
-/** Insert a set of rows into a table
- *
- * This function inserts the data from "rowSet" into "tableName".
- *
- * "rowSet" is a psArray of psMetadata containing row specifications identical to
- * those used in psDBInsertOneRow().
- *
- * @return true on success
- */
-bool psDBInsertRows(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    psArray *rowSet                     ///< Set of rows to insert
-);
-
-/** Retrieves all rows from a table
- *
- * This function fetches all rows as an psArray of psMetadata.  The rows are in
- * the same psMetadata format as used in psDBInsertOneRow() & psDBInsertRows().
- *
- * @return A psArray of psMetadata or NULL on failure
- */
-psArray *psDBDumpRows(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName               ///< Table name
-);
-
-/** Retrieves all columns from a table
- *
- * This function fetches all columns, as either a psVector or a psArray
- * depending on whether or not the column is numeric, and return them in a
- * psMetadata structure where psMetadataItem.name contains the column's name.
- *
- * @return A psMetadata containing either a psArrays or psVector per column
- */
-psMetadata *psDBDumpCols(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName               ///< Table name
-);
-
-/** Updates the field values, as specified, in a table
- *
- * This function updates the fields contained in "values" in the row(s) that
- * have a field with the value indicated by "where".  Where "where" is in the
- * same format as used in psDBSelectRows().
- *
- * The "values" specification uses the same format as the row specification
- * used in psDBInsertOneRow(), etc.
- *
- * @return The number of rows modified or a negative value on error
- */
-psS64 psDBUpdateRows(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,              ///< Table name
-    psMetadata *where,                  ///< Row match criteria
-    psMetadata *values                  ///< new field values
-);
-
-/** Deletes rows, as specified, in a table
- *
- * Delete the rows that are matched by "where" using the same semantics for
- * "where" as in psDBUpdateRow().
- *
- * If "where" is NULL, all rows in the table will be removed and regardless of
- * the number of rows that were dropped, only 1 will be returned on success.
- *
- * @return The number of rows removed or a negative value on error
- */
-psS64 psDBDeleteRows(
-    psDB *dbh,                          ///< Database handle
-    const char *tableName,             ///< Table name
-    psMetadata *where                  ///< Row match criteria
-);
-
-/// @}
-
-#endif // BUILD_PSDB
-
-#endif // PS_DB_H
Index: trunk/psLib/src/astronomy/psMetadata.c
===================================================================
--- trunk/psLib/src/astronomy/psMetadata.c	(revision 3690)
+++ 	(revision )
@@ -1,729 +1,0 @@
-/** @file  psMetadata.c
-*
-*
-*  @brief Contains metadata structures, enumerations and functions prototypes.
-*
-*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
-*  prototypes necessary creating psLib metadata APIs
-*
-*  @ingroup Metadata
-*
-*  @author Robert DeSonia, MHPCC
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.58 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-07 20:27:41 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
-
-/******************************************************************************/
-/*  INCLUDE FILES                                                             */
-/******************************************************************************/
-#include<stdio.h>
-#include<stdarg.h>
-#include<string.h>
-
-#include "fitsio.h"
-#include "psType.h"
-#include "psMemory.h"
-#include "psError.h"
-#include "psAbort.h"
-#include "psList.h"
-#include "psHash.h"
-#include "psVector.h"
-#include "psMetadata.h"
-#include "psLookupTable.h"
-#include "psString.h"
-#include "psAstronomyErrors.h"
-#include "psConstants.h"
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-
-/** Maximum size of a string */
-#define MAX_STRING_LENGTH 1024
-
-/******************************************************************************/
-/*  TYPE DEFINITIONS                                                          */
-/******************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FILE STATIC VARIABLES                                                    */
-/*****************************************************************************/
-
-static psS32 metadataId = 0;
-
-/*****************************************************************************/
-/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
-/*****************************************************************************/
-
-static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
-{
-
-    if (existing != NULL && existing->type == PS_META_MULTI) {
-        return existing;
-    }
-
-    // move any existing entry into a psList
-    psList* newList = psListAlloc(existing);
-
-    psMetadataItem* item = psMetadataItemAlloc(key,
-                           PS_META_MULTI,
-                           "",
-                           newList);
-
-    if (existing != NULL) {
-        psHashRemove(table,key); // take out the old entry
-    }
-
-    psHashAdd(table, key, item); // put in the new entry
-
-    // free local references of newly allocated items.
-    psFree(newList);
-    psFree(item);
-
-    return item;
-}
-
-static void metadataItemFree(psMetadataItem* metadataItem)
-{
-    psMetadataType type;
-
-    type = metadataItem->type;
-
-    if (metadataItem == NULL) {
-        return;
-    }
-
-    psFree(metadataItem->name);
-    psFree(metadataItem->comment);
-    if (! PS_META_IS_PRIMITIVE(type)) {
-        psFree(metadataItem->data.V);
-    }
-}
-
-static void metadataIteratorFree(psMetadataIterator* iter)
-{
-    if (iter == NULL) {
-        return;
-    }
-    psFree(iter->iter);
-
-    if (iter->preg != NULL) {
-        regfree(iter->preg);
-    }
-}
-
-static void metadataFree(psMetadata* metadata)
-{
-    if (metadata == NULL) {
-        return;
-    }
-    psFree(metadata->list);
-    psFree(metadata->table);
-}
-
-/*****************************************************************************/
-/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
-/*****************************************************************************/
-
-psMetadataItem* psMetadataItemAlloc(const char *name, psMetadataType type,
-                                    const char *comment, ...)
-{
-    va_list argPtr;
-    psMetadataItem* metadataItem = NULL;
-
-    // Get the variable list parameters to pass to allocation function
-    va_start(argPtr, comment);
-
-    // Call metadata item allocation
-    metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
-
-    // Clean up stack after variable arguement has been used
-    va_end(argPtr);
-
-    return metadataItem;
-}
-
-#define METADATAITEM_ALLOC_TYPE(NAME,TYPE,METATYPE) \
-psMetadataItem* psMetadataItemAlloc##NAME(const char* name, \
-        const char* comment, \
-        TYPE value) \
-{ \
-    return psMetadataItemAlloc(name, METATYPE, comment, value); \
-}
-
-METADATAITEM_ALLOC_TYPE(Str,const char*,PS_META_STR)
-METADATAITEM_ALLOC_TYPE(F32,psF32,PS_META_F32)
-METADATAITEM_ALLOC_TYPE(F64,psF64,PS_META_F64)
-METADATAITEM_ALLOC_TYPE(S32,psS32,PS_META_S32)
-METADATAITEM_ALLOC_TYPE(Bool,psBool,PS_META_BOOL)
-
-psMetadataItem* psMetadataItemAllocV(const char *name, psMetadataType type,
-                                     const char *comment, va_list argPtr)
-{
-    psMetadataItem* metadataItem = NULL;
-
-
-    PS_PTR_CHECK_NULL(name,NULL);
-
-    // Allocate metadata item
-    metadataItem = (psMetadataItem*) psAlloc(sizeof(psMetadataItem));
-    metadataItem->data.V = NULL;
-
-    // Set deallocator
-    psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
-
-    // Allocate and set metadata item comment
-    metadataItem->comment = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
-    if (comment == NULL) {
-        // Per SDRS, null isn't allowed, must use "" instead
-        strncpy(metadataItem->comment, "", MAX_STRING_LENGTH);
-    } else {
-        strncpy(metadataItem->comment, comment, MAX_STRING_LENGTH);
-    }
-
-    // Set metadata item unique id
-    *(psS32 *)(&metadataItem->id) = ++metadataId;
-
-    // Set metadata item type
-    metadataItem->type = type & PS_METADATA_TYPE_MASK;
-
-    // Allocate and set metadata item name
-    metadataItem->name = (char *)psAlloc(sizeof(char) * MAX_STRING_LENGTH);
-    vsprintf(metadataItem->name, name, argPtr);
-
-    // Set metadata item value
-    switch(metadataItem->type) {
-    case PS_META_BOOL:
-        metadataItem->data.B = (psBool)va_arg(argPtr, psS32);
-        break;
-    case PS_META_S32:
-        metadataItem->data.S32 = (psS32)va_arg(argPtr, psS32);
-        break;
-    case PS_META_F32:
-        metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
-        break;
-    case PS_META_F64:
-        metadataItem->data.F64 = (psF64)va_arg(argPtr, psF64);
-        break;
-    case PS_META_STR:
-        // Perform copy of input strings
-        metadataItem->data.V = psStringNCopy(va_arg(argPtr, char *), MAX_STRING_LENGTH);
-        break;
-    case PS_META_LIST:
-    case PS_META_VEC:
-    case PS_META_HASH:
-    case PS_META_LOOKUPTABLE:
-    case PS_META_JPEG:
-    case PS_META_PNG:
-    case PS_META_ASTROM:
-    case PS_META_UNKNOWN:
-    case PS_META_MULTI:
-        // Copy of input data not performed due to variability of data types
-        metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
-        break;
-    default:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, type);
-        psFree(metadataItem);
-        metadataItem = NULL;
-    }
-
-    return metadataItem;
-}
-
-psMetadata* psMetadataAlloc(void)
-{
-    psList* list = NULL;
-    psHash* table = NULL;
-    psMetadata* metadata = NULL;
-
-    // Allocate metadata
-    metadata = (psMetadata*) psAlloc(sizeof(psMetadata));
-    // Set deallocator
-    psMemSetDeallocator(metadata, (psFreeFcn) metadataFree);
-
-    // Allocate metadata's internal containers
-    list = (psList*) psListAlloc(NULL);
-    table = (psHash*) psHashAlloc(10);
-
-    metadata->list = list;
-    metadata->table = table;
-
-    return metadata;
-}
-
-psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location, psS32 flags)
-{
-    char * key = NULL;
-    psHash *mdTable = NULL;
-    psList *mdList = NULL;
-    psMetadataItem *existingEntry = NULL;
-
-    PS_PTR_CHECK_NULL(md,NULL);
-    PS_PTR_CHECK_NULL(md->table,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-    PS_PTR_CHECK_NULL(metadataItem,NULL);
-    PS_PTR_CHECK_NULL(metadataItem->name,NULL);
-
-    mdTable = md->table;
-    mdList = md->list;
-    key = metadataItem->name;
-
-    // See if key is already in table
-    existingEntry = (psMetadataItem*)psHashLookup(mdTable, key);
-
-    if (metadataItem->type == PS_META_MULTI) {
-        // the incoming entry is PS_META_MULTI
-
-        // force the hash entry to be PS_META_MULTI
-        existingEntry = makeMetaMulti(mdTable,key,existingEntry);
-
-        // add all the items in the incoming entry to metadata
-        psList* list = metadataItem->data.list;
-        if (list != NULL) {
-            psListIterator* iter = psListIteratorAlloc(list,PS_LIST_HEAD,true);
-            psMetadataItem* listItem;
-            while ((listItem=(psMetadataItem*)psListGetAndIncrement(iter)) != NULL) {
-                psMetadataAddItem(md,listItem,location,flags);
-            }
-            psFree(iter);
-        }
-
-        return true; // all done.
-    }
-
-    // how the item is added to the hash depends on prior existence, flags, etc.
-    if(existingEntry != NULL) { // prior existence
-        if (existingEntry->type == PS_META_MULTI || (flags & PS_META_DUPLICATE_OK) != 0) {
-            // duplicate entries allowed - add another entry.
-
-            // make sure the existing entry is PS_META_MULTI
-            existingEntry = makeMetaMulti(mdTable,key,existingEntry);
-
-            // add to the hash's list of duplicate entries
-            if (! psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem) ) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-                return false;
-            }
-        } else if ((flags & PS_META_REPLACE) != 0) {
-            // replace entry instead of creating a duplicate entry.
-
-            // remove the existing entry from metadata
-            psMetadataRemove(md,0,key);
-
-            // treat as if new (added to list below)
-            if(!psHashAdd(mdTable, key, metadataItem)) {
-                psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-                return false;
-            }
-        } else {
-            // default is to error on duplicate entry.
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
-            return false;
-        }
-    } else {
-        // OK, this is a new item.
-
-        // Node doesn't exist - Add new metadata item to metadata collection's hash
-        if(!psHashAdd(mdTable, key, metadataItem)) {
-            psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
-            return false;
-        }
-    }
-
-    if(!psListAdd(mdList, location, metadataItem)) {
-        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
-        return false;
-    }
-
-    return true;
-}
-
-psBool psMetadataAdd(psMetadata *md, psS32 location, const char *name,
-                     psS32 type, const char *comment, ...)
-{
-    va_list argPtr;
-
-    va_start(argPtr, comment);
-    psBool result = psMetadataAddV(md,location,name,type,comment,argPtr);
-    va_end(argPtr);
-
-    return result;
-}
-
-psBool psMetadataAddV(psMetadata *md, psS32 location, const char *name,
-                      psS32 type, const char *comment, va_list list)
-{
-    psMetadataItem* metadataItem = NULL;
-
-    metadataItem = psMetadataItemAllocV(name, type & PS_METADATA_TYPE_MASK, comment, list);
-
-    if (!psMetadataAddItem(md, metadataItem, location, type & PS_METADATA_FLAGS_MASK)) {
-        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_FAILED);
-        psFree(metadataItem);
-        return false;
-    }
-    // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
-    psFree(metadataItem);
-
-    return true;
-}
-
-#define METADATA_ADD_TYPE(NAME,TYPE,METATYPE) \
-psBool psMetadataAdd##NAME(psMetadata* md, psS32 where, const char* name, \
-                           const char* comment, TYPE value) { \
-    return psMetadataAdd(md,where,name, METATYPE,comment,value); \
-}
-
-METADATA_ADD_TYPE(S32,psS32,PS_META_S32)
-METADATA_ADD_TYPE(F32,psF32,PS_META_F32)
-METADATA_ADD_TYPE(F64,psF64,PS_META_F64)
-METADATA_ADD_TYPE(List,psList*,PS_META_LIST)
-METADATA_ADD_TYPE(Str,const char*,PS_META_STR)
-METADATA_ADD_TYPE(Vector,psVector*,PS_META_VEC)
-METADATA_ADD_TYPE(Image,psImage*,PS_META_IMG)
-METADATA_ADD_TYPE(Hash,psHash*,PS_META_HASH)
-METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_META_LOOKUPTABLE)
-METADATA_ADD_TYPE(Unknown,void*,PS_META_UNKNOWN)
-
-psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
-{
-    PS_PTR_CHECK_NULL(md,NULL);
-
-    PS_PTR_CHECK_NULL(md->list,NULL);
-    psList* mdList = md->list;
-
-    PS_PTR_CHECK_NULL(md->table,NULL);
-    psHash* mdTable = md->table;
-
-    // Select removal by key or index
-    if (key != NULL) {
-        // Remove by key name
-        psMetadataItem* entry = psHashLookup(mdTable,key);
-        if (entry == NULL) {
-            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-            return false;
-        }
-        if (entry->type == PS_META_MULTI) {
-            psMetadataItem* listItem;
-            psListIterator* iter = psListIteratorAlloc(
-                                       entry->data.list,
-                                       PS_LIST_HEAD,true);
-            while ((listItem=psListGetAndIncrement(iter)) != NULL) {
-                psListRemoveData(mdList, listItem);
-            }
-            psFree(iter);
-            psHashRemove(mdTable,key);
-
-        } else {
-            psListRemoveData(mdList, entry);
-            psHashRemove(mdTable, key);
-        }
-    } else {
-        // Remove by index
-        psMetadataItem* entry = psListGet(mdList, where);
-        if (entry == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
-            return false;
-        }
-        key = entry->name;
-
-        if (key == NULL) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_REMOVE_LIST_INDEX_FAILED, where);
-            return false;
-        }
-
-        psMetadataItem* tableItem = psHashLookup(mdTable, key);
-        if (tableItem == NULL) {
-            psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-            return false;
-        }
-
-        if (tableItem->type == PS_META_MULTI) {
-            // multiple entries with same key, remove just the specified one
-            psListRemoveData(tableItem->data.list, entry);
-        } else {
-            if (!psHashRemove(mdTable, key)) {
-                psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
-                return false;
-            }
-        }
-        psListRemove(mdList, where);
-    }
-
-    return true;
-}
-
-psMetadataItem* psMetadataLookup(psMetadata *md, const char *key)
-{
-    psHash* mdTable = NULL;
-    psMetadataItem* entry = NULL;
-
-
-    PS_PTR_CHECK_NULL(md,NULL);
-    PS_PTR_CHECK_NULL(md->table,NULL);
-    PS_PTR_CHECK_NULL(key,NULL);
-
-    mdTable = md->table;
-    entry = (psMetadataItem*)psHashLookup(mdTable, key);
-
-    return entry;
-}
-
-void* psMetadataLookupPtr(psBool *status, psMetadata *md, const char *key)
-{
-    psMetadataItem *metadataItem = NULL;
-
-    if (status) {
-        *status = true;
-    }
-
-    metadataItem = psMetadataLookup(md, key);
-    if(metadataItem == NULL) {
-        if (status) {
-            *status = false;
-        }
-        return NULL;
-    }
-    if (metadataItem->type == PS_META_MULTI) {
-        // if multiple keys found, use the first.
-        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
-    }
-
-    if(PS_META_IS_PRIMITIVE(metadataItem->type)) {
-        if (status) {
-            *status = false;
-        }
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
-                metadataItem->type);
-        return NULL;
-    } else {
-        return metadataItem->data.V;
-    }
-}
-
-#define psMetadataLookupNumTYPE(TYPE) \
-ps##TYPE psMetadataLookup##TYPE(psBool *status, psMetadata *md, const char *key) \
-{ \
-    psMetadataItem *metadataItem = NULL; \
-    ps##TYPE value = 0; \
-    \
-    if (status) { \
-        *status = true; \
-    } \
-    \
-    metadataItem = psMetadataLookup(md, key); \
-    if(metadataItem == NULL) { \
-        if (status) { \
-            *status = false; \
-        } \
-        return 0; \
-    } \
-    if (metadataItem->type == PS_META_MULTI) { \
-        /* if multiple keys found, use the first. */ \
-        metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
-    } \
-    \
-    switch (metadataItem->type) { \
-    case PS_META_S32: \
-        value = (ps##TYPE)metadataItem->data.S32; \
-        break; \
-    case PS_META_F32: \
-        value = (ps##TYPE)metadataItem->data.F32; \
-        break; \
-    case PS_META_F64: \
-        value = (ps##TYPE)metadataItem->data.F64; \
-        break; \
-    case PS_META_BOOL: \
-        if (metadataItem->data.B) { \
-            value = 1; \
-        } \
-        break; \
-    default: \
-        /* if you get to this point, the value is not a number. */ \
-        if (status) { \
-            *status = false; \
-        } \
-        break; \
-    } \
-    \
-    /* psFree(metadataItem); currently, the lookup doesn't increment the ref count */ \
-    return value; \
-}
-
-psMetadataLookupNumTYPE(F32)
-psMetadataLookupNumTYPE(F64)
-psMetadataLookupNumTYPE(S32)
-psMetadataLookupNumTYPE(Bool)
-
-psMetadataItem* psMetadataGet(psMetadata *md, psS32 where)
-{
-    psMetadataItem* entry = NULL;
-
-    PS_PTR_CHECK_NULL(md,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-
-    entry = (psMetadataItem*) psListGet(md->list, where);
-    if (entry == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
-        return NULL;
-    }
-
-    return entry;
-}
-
-psMetadataIterator* psMetadataIteratorAlloc(psMetadata* md,
-        int location,
-        const char* regex)
-{
-    PS_PTR_CHECK_NULL(md,NULL);
-    PS_PTR_CHECK_NULL(md->list,NULL);
-
-    psMetadataIterator* newIter = psAlloc(sizeof(psMetadataIterator));
-    newIter->preg = NULL;
-    newIter->iter = NULL;
-
-    // Set deallocator
-    psMemSetDeallocator(newIter, (psFreeFcn) metadataIteratorFree);
-
-    if (regex == NULL) {
-        newIter->iter = psListIteratorAlloc(md->list, location, false);
-        return newIter;
-    } else {
-        int regRtn = regcomp(newIter->preg,regex,0);
-        if (regRtn != 0) {
-            char errMsg[256];
-            regerror(regRtn, newIter->preg, errMsg, 256);
-            regfree(newIter->preg);
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    PS_ERRORTEXT_psMetadata_REGEX_INVALID,
-                    errMsg);
-            psFree(newIter);
-            return NULL;
-        }
-    }
-
-    psMetadataIteratorSet(newIter, location); // XXX: do we error if no match is found?
-
-    return newIter;
-}
-
-psBool psMetadataIteratorSet(psMetadataIterator* iterator,
-                             int location)
-{
-    int match;
-    psMetadataItem* cursor;
-
-    PS_PTR_CHECK_NULL(iterator,NULL);
-
-    psListIterator* iter = iterator->iter;
-    PS_PTR_CHECK_NULL(iterator->iter,NULL);
-
-    regex_t* preg = iterator->preg;
-
-    // handle trivial case where no regex subsetting is required.
-    if (preg == NULL) {
-        return psListIteratorSet(iter,location);
-    }
-
-    if (location < 0) {
-        // match from the tail
-        match = 0;
-        psListIteratorSet(iter,PS_LIST_TAIL);
-        while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
-            if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
-                // this key is a match
-                match--;
-                if (match == location) {
-                    break;
-                }
-            }
-            (void)psListGetAndDecrement(iter);
-        }
-        return (match == location);
-    }
-
-    // find the n-th match from the head
-    match = -1;
-    psListIteratorSet(iter,PS_LIST_HEAD);
-    while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
-        if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
-            // this key is a match
-            match++;
-            if (match == location) {
-                break;
-            }
-        }
-        (void)psListGetAndIncrement(iter);
-    }
-    return (match == location);
-}
-
-psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
-{
-    psMetadataItem* oldValue;
-
-    PS_PTR_CHECK_NULL(iterator,NULL);
-
-    psListIterator* iter = iterator->iter;
-    PS_PTR_CHECK_NULL(iterator->iter,NULL);
-
-    regex_t* preg = iterator->preg;
-
-    // handle trivial case where no regex subsetting is required.
-    if (preg == NULL) {
-        return (psMetadataItem*)psListGetAndIncrement(iter);
-    }
-
-    oldValue = (psMetadataItem*)iter->cursor;
-
-    while (psListGetAndIncrement(iter) != NULL) {
-        if (iter->cursor != NULL &&
-                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
-            // this key is a match
-            break;
-        }
-    }
-    return oldValue;
-}
-
-psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
-{
-    psMetadataItem* oldValue;
-
-    PS_PTR_CHECK_NULL(iterator,NULL);
-
-    psListIterator* iter = iterator->iter;
-    PS_PTR_CHECK_NULL(iterator->iter,NULL);
-
-    regex_t* preg = iterator->preg;
-
-    // handle trivial case where no regex subsetting is required.
-    if (preg == NULL) {
-        return (psMetadataItem*)psListGetAndDecrement(iter);
-    }
-
-    oldValue = (psMetadataItem*)iter->cursor;
-
-    while (psListGetAndDecrement(iter) != NULL) {
-        if (iter->cursor != NULL &&
-                regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
-            // this key is a match
-            break;
-        }
-    }
-    return oldValue;
-}
Index: trunk/psLib/src/astronomy/psMetadata.h
===================================================================
--- trunk/psLib/src/astronomy/psMetadata.h	(revision 3690)
+++ 	(revision )
@@ -1,479 +1,0 @@
-/** @file  psMetadata.h
-*
-*  @brief Contains metadata struuctures, enumerations and functions prototypes
-*
-*  This file defines metadata item, metadata type, metadata flags, metadata containers, and function
-*  prototypes necessary creating psLib metadata APIs
-*
-*  @ingroup Metadata
-*
-*  @author Robert DeSonia, MHPCC
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.44 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-08 17:58:57 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
-#ifndef PS_METADATA_H
-#define PS_METADATA_H
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <regex.h>
-
-#include "psHash.h"
-#include "psList.h"
-#include "psImage.h"
-#include "psLookupTable.h"
-
-/// @addtogroup Metadata
-/// @{
-
-/** Metadata item type.
- *
- * Enumeration for maintaining metadata item types.
- */
-typedef enum {
-    PS_META_S32 = PS_TYPE_S32,         ///< psS32 primitive data.
-    PS_META_F32 = PS_TYPE_F32,         ///< psF32 primitive data.
-    PS_META_F64 = PS_TYPE_F64,         ///< psF64 primitive data.
-    PS_META_BOOL = PS_TYPE_BOOL,       ///< psBool primitive data.
-    PS_META_LIST = 0x10000,            ///< List data (Stored as item.data.list).
-    PS_META_STR,                       ///< String data (Stored as item.data.V).
-    PS_META_VEC,                       ///< Vector data (Stored as item.data.V).
-    PS_META_IMG,                       ///< Image data (Stored as item.data.V).
-    PS_META_HASH,                      ///< Hash data (Stored as item.data.V).
-    PS_META_LOOKUPTABLE,               ///< Lookup table data (Stored as item.data.V).
-    PS_META_JPEG,                      ///< JPEG data (Stored as item.data.V).
-    PS_META_PNG,                       ///< PNG data (Stored as item.data.V).
-    PS_META_ASTROM,                    ///< Astrometric coefficients (Stored as item.data.V).
-    PS_META_UNKNOWN,                   ///< Other data (Stored as item.data.V).
-    PS_META_MULTI                      ///< Used internally, do not create an metadata item of this type.
-} psMetadataType;
-
-#define PS_META_IS_PRIMITIVE(TYPE) \
-(TYPE == PS_META_S32 || \
- TYPE == PS_META_F32 || \
- TYPE == PS_META_F64 || \
- TYPE == PS_META_BOOL)
-
-#define PS_META_PRIMITIVE_TYPE(METATYPE) ( \
-        (METATYPE==PS_META_S32) ? PS_TYPE_S32 : \
-        (METATYPE==PS_META_F32) ? PS_TYPE_F32 : \
-        (METATYPE==PS_META_F64) ? PS_TYPE_F64 : \
-        (METATYPE==PS_META_BOOL) ? PS_TYPE_BOOL : 0 )
-
-/** Option flags for psMetadata functions
- *
- *  Enumeration for the modification of the behaviour in psMetadataAddItem.
- * 
- *  @see psMetadataAddItem
- */
-typedef enum {
-    PS_META_DEFAULT = 0,               ///< default behaviour (duplicate entry is an error)
-    PS_META_REPLACE = 0x1000000,       ///< allow entry to be replaced
-    PS_META_DUPLICATE_OK = 0x2000000   ///< allow duplicate entries
-} psMetadataFlags;
-
-#define PS_METADATA_FLAGS_MASK 0xFF000000
-#define PS_METADATA_TYPE_MASK 0x00FFFFFF
-
-/** Metadata data structure.
- *
- *  Struct for holding metadata items. Metadata items are held in two
- *  containers. The first employs a doubly-linked list to preserve the order
- *  of the metadata. The second container employs a hash table which
- *  allows fast lookup when given a metadata keyword.
- */
-typedef struct psMetadata
-{
-    psList*  list;                     ///< Metadata in linked-list
-    psHash*  table;                    ///< Metadata in a hash table
-}
-psMetadata;
-
-/** Metadata iterator
- *
- *  Iterator for metadata.
- */
-typedef struct
-{
-    psListIterator* iter;              ///< iterator for the psMetadata's psList
-    regex_t* preg;                     ///< the subsetting regular expression
-}
-psMetadataIterator;
-
-
-/** Metadata item data structure.
- *
- * Struct for maintaining metadata items of varying types. It also contains
- * information about the item name, flags, comments, and other items with the same name.
- */
-typedef struct psMetadataItem
-{
-    const psS32 id;                    ///< Unique ID for metadata item.
-    char *name;                        ///< Name of metadata item.
-    psMetadataType type;               ///< Type of metadata item.
-    union {
-        psBool B;                      ///< boolean data
-        psS32 S32;                     ///< Signed 32-bit integer data.
-        psF32 F32;                     ///< Single-precision float data.
-        psF64 F64;                     ///< Double-precision float data.
-        psList *list;                  ///< List data.
-        psMetadata *md;                ///< Metadata data.
-        psPtr V;                       ///< Pointer to other type of data.
-    } data;                            ///< Union for data types.
-    char *comment;                     ///< Optional comment ("", not NULL).
-}
-psMetadataItem;
-
-/** Create a metadata item.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct. The name argument specifies the name to use for this item, and
- *  may include sprintf formatting codes. The format entry specifies both
- *  the metadata type and optional flags and is created by bit-wise or of the
- *  appropriate type and flag. The comment argument is a fixed string used to
- *  comment the metadata item. The arguments to the name formatting codes and
- *  the metadata itself are passed as arguments following the comment string.
- *  The data must be a pointer for any of the elements stored in data.void.
- *  The argument list must be interpreted appropriately by the va_list
- *  operators in the function specified size and type.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAlloc(
-    const char *name,                  ///< Name of metadata item.
-    psMetadataType type,               ///< Type of metadata item.
-    const char *comment,               ///< Comment for metadata item.
-    ...                                ///< Arguments for name formatting and metadata item data.
-);
-
-/** Create a metadata item with specified string data.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocStr(
-    const char* name,                  ///< Name of metadata item.
-    const char* comment,               ///< Comment for metadata item.
-    const char* value                  ///< the value of the metadata item.
-);
-
-/** Create a metadata item with specified psF32 data.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocF32(
-    const char* name,                  ///< Name of metadata item.
-    const char* comment,               ///< Comment for metadata item.
-    psF32 value                        ///< the value of the metadata item.
-);
-
-/** Create a metadata item with specified psF64 data.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocF64(
-    const char* name,                  ///< Name of metadata item.
-    const char* comment,               ///< Comment for metadata item.
-    psF64 value                        ///< the value of the metadata item.
-);
-
-/** Create a metadata item with specified psS32 data.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocS32(
-    const char* name,                  ///< Name of metadata item.
-    const char* comment,               ///< Comment for metadata item.
-    psS32 value                        ///< the value of the metadata item.
-);
-
-/** Create a metadata item with specified psBool data.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocBool(
-    const char* name,                  ///< Name of metadata item.
-    const char* comment,               ///< Comment for metadata item.
-    psBool value                       ///< the value of the metadata item.
-);
-
-#ifndef SWIG
-/** Create a metadata item with va_list.
- *
- *  Returns a fill psMetadataItem ready for insertion into the psMetadata
- *  struct. The name argument specifies the name to use for this item, and
- *  may include sprintf formatting codes. The format entry specifies both
- *  the metadata type and optional flags and is created by bit-wise or of the
- *  appropriate type and flag. The comment argument is a fixed string used to
- *  comment the metadata item. The arguments to the name formatting codes and
- *  the metadata itself are passed as arguments following the comment string.
- *  The data must be a pointer for any of the elements stored in data.void.
- *  The argument list must be interpreted appropriately by the va_list
- *  operators in the function specified size and type.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataItemAllocV(
-    const char *name,                  ///< Name of metadata item.
-    psMetadataType type,               ///< Type of metadata item.
-    const char *comment,               ///< Comment for metadata item.
-    va_list list                       ///< Arguments for name formatting and metadata item data.
-);
-#endif
-
-/** Create a metadata collection.
- *
- *  Returns an empty metadata container with fully allocated internal metadata
- *  containers.
- *
- *  @return psMetadata* : Pointer metadata.
- */
-psMetadata* psMetadataAlloc(void);
-
-/** Add existing metadata item to metadata collection.
- *
- *  Add a metadata item that has already been created to the metadata
- *  collection.
- *
- *  @return bool: True for success, false for failure.
- */
-psBool psMetadataAddItem(
-    psMetadata*  md,                   ///< Metadata collection to insert metadat item.
-    psMetadataItem*  item,             ///< Metadata item to be added.
-    psS32 location,                    ///< Location to be added.
-    psS32 flags                        ///< Options flag mask, see psMetadataFlags enum
-);
-
-/** Create and add a metadata item to metadata collection.
- *
- * Creates a new metadata item add to the metadata collection.
- *
- * @return bool: True for success, false for failure.
- */
-psBool psMetadataAdd(
-    psMetadata* md,                    ///< Metadata collection to insert metadata item.
-    psS32 location,                    ///< Location to be added.
-    const char *name,                  ///< Name of metadata item.
-    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
-    const char *comment,               ///< Comment for metadata item.
-    ...                                ///< Arguments for name formatting and metadata item data.
-);
-
-#ifndef SWIG
-/** Create and add a metadata item to metadata collection.
- *
- * Creates a new metadata item add to the metadata collection.
- *
- * @return bool: True for success, false for failure.
- */
-psBool psMetadataAddV(
-    psMetadata* md,                    ///< Metadata collection to insert metadat item.
-    psS32 location,                    ///< Location to be added.
-    const char *name,                  ///< Name of metadata item.
-    int type,                          ///< Type of metadata item (psMetadataType) and options (psMetadataFlags)
-    const char *comment,               ///< Comment for metadata item.
-    va_list list                       ///< Arguments for name formatting and metadata item data.
-);
-#endif
-
-psBool psMetadataAddS32(psMetadata* md, psS32 location, const char* name,
-                        const char* comment, psS32 value);
-psBool psMetadataAddF32(psMetadata* md, psS32 location, const char* name,
-                        const char* comment, psF32 value);
-psBool psMetadataAddF64(psMetadata* md, psS32 location, const char* name,
-                        const char* comment, psF64 value);
-psBool psMetadataAddList(psMetadata* md, psS32 location, const char* name,
-                         const char* comment, psList* value);
-psBool psMetadataAddStr(psMetadata* md, psS32 location, const char* name,
-                        const char* comment, const char* value);
-psBool psMetadataAddVector(psMetadata* md, psS32 location, const char* name,
-                           const char* comment, psVector* value);
-psBool psMetadataAddImage(psMetadata* md, psS32 location, const char* name,
-                          const char* comment, psImage* value);
-psBool psMetadataAddHash(psMetadata* md, psS32 location, const char* name,
-                         const char* comment, psHash* value);
-psBool psMetadataAddLookupTable(psMetadata* md, psS32 location, const char* name,
-                                const char* comment, psLookupTable* value);
-psBool psMetadataAddUnknown(psMetadata* md, psS32 location, const char* name,
-                            const char* comment, psPtr value);
-
-/** Remove an item from metadata collection.
- *
- *  Items may be removed from metadata by specifing a key or location. If the
- *  name is null, the where argument is used instead. If name is not null,
- *  where is set to PS_LIST_UNKNOWN. If the item is found, it is removed from
- *  the metadata and true is returned.  If the key is not unique, then all
- *  items corresponding to it are removed.
- *
- * @return bool: True for success, false for failure.
- */
-psBool psMetadataRemove(
-    psMetadata*  md,           ///< Metadata collection to remove metadata item.
-    psS32 where,               ///< Location to be removed.
-    const char * key           ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the first item is returned. If the item is not found, null is
- *  returned.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataLookup(
-    psMetadata * md,                   ///< Metadata collection to lookup metadata item.
-    const char * key                   ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name and return its double precision value.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the value of the first item is returned. If the item is not found, zero is
- *  returned.
- *
- * @return psF64 : Value of metadata item.
- */
-psF64 psMetadataLookupF64(
-    psBool *status,                    ///< Status of lookup.
-    psMetadata *md,                    ///< Metadata collection to lookup metadata item.
-    const char *key                    ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name and return its single precision value.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the value of the first item is returned. If the item is not found, zero is
- *  returned.
- *
- * @return psF32 : Value of metadata item.
- */
-psF32 psMetadataLookupF32(
-    psBool *status,                    ///< Status of lookup.
-    psMetadata *md,                    ///< Metadata collection to lookup metadata item.
-    const char *key                    ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name and return its integer value.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the value of the first item is returned. If the item is not found, zero is
- *  returned.
- *
- * @return psS32 : Value of metadata item.
- */
-psS32 psMetadataLookupS32(
-    psBool *status,                    ///< Status of lookup.
-    psMetadata *md,                    ///< Metadata collection to lookup metadata item.
-    const char *key                    ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name and return its boolean value.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the value of the first item is returned. If the item is not found, zero is
- *  returned.
- *
- * @return psBool : Value of metadata item.
- */
-psBool psMetadataLookupBool(
-    psBool *status,                    ///< Status of lookup.
-    psMetadata *md,                    ///< Metadata collection to lookup metadata item.
-    const char *key                    ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on key name and return its integer value.
- *
- *  Items may be found in the metadata by providing a key. If the key is
- *  non-unique, the value of the first item is returned. If the item is not found, zero is
- *  returned.
- *
- * @return void* : Value of metadata item.
- */
-psPtr psMetadataLookupPtr(
-    psBool *status,                    ///< Status of lookup.
-    psMetadata* md,                    ///< Metadata collection to lookup metadata item.
-    const char *key                    ///< Name of metadata key.
-);
-
-/** Find an item in the metadata collection based on list index.
- *
- *  Items may be found in the metadata by their entry position in the list
- *  container.
- *
- *  @return psMetadataItem* : Pointer metadata item.
- */
-psMetadataItem* psMetadataGet(
-    psMetadata*  md,                   ///< Metadata collection to insert metadat item.
-    psS32 location                     ///< Location to be retrieved.
-);
-
-/** Creates a psMetadataIterator to iterate over the specified psMetadata.
- *
- *  Supports the subsetting of the metadata via keyword using regular
- *  expression.  If no regular expression is specified, iteration
- *  over the entire psMetadata is performed.
- *
- *  @return psMetadataIterator*        a new psMetadataIterator, of NULL if error occurred
- */
-psMetadataIterator* psMetadataIteratorAlloc(
-    psMetadata* md,                    ///< the psMetadata to iterate with
-    int location,                      ///< the initial starting point (after subsetting).
-    const char* regex
-    ///< A regular expression for subsetting the psMetadata.  If NULL, no
-    ///< subsetting is performed.
-);
-
-/** Set the iterator of the psMetadat to a given position.  If location is
- *  invalid the iterator position is not changed.
- *
- *  @return psBool        TRUE if iterator successfully set, otherwise FALSE.
-*/
-psBool psMetadataIteratorSet(
-    psMetadataIterator* iterator,      ///< psMetadata iterator
-    int location                       ///< index number, PS_LIST_HEAD, or PS_LIST_TAIL
-);
-
-/** Position the specified iterator to the next matching item in psMetadata,
- *  given the regular expression of the iterator
- *
- *  @return psPtr       the psMetadataItem at the original iterator position
- *                      or NULL if the iterator went past the end of the list.
- */
-psMetadataItem* psMetadataGetAndIncrement(
-    psMetadataIterator* iterator           ///< iterator to move
-);
-
-/** Position the specified iterator to the previous matching item in psMetadata,
- *  given the regular expression of the iterator
- *
- *  @return psPtr       the psMetadataItem at the original iterator position
- *                      or NULL if the iterator went past the beginning of the
- *                      list.
- */
-psMetadataItem* psMetadataGetAndDecrement(
-    psMetadataIterator* iterator           ///< iterator to move
-);
-
-/// @}
-
-#endif
Index: trunk/psLib/src/astronomy/psMetadataIO.c
===================================================================
--- trunk/psLib/src/astronomy/psMetadataIO.c	(revision 3690)
+++ 	(revision )
@@ -1,1168 +1,0 @@
-/** @file  psMetadataIO.c
-*
-*  @brief Contains metadata input/output functions.
-*
-*  This file defines functions to read and write metadata to/from an external file.
-*
-*  @ingroup Metadata
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-06 01:12:58 $
-*
-*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
-*/
-
-#include <libxml/parser.h>
-#include <fitsio.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-
-#include "psAbort.h"
-#include "psType.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"
-
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-
-/** 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;
-
-/** Free and null temporary variables used by config file parser */
-#define CLEAR_TEMPS()                                                                                        \
-if(strName) {                                                                                                \
-    psFree(strName);                                                                                         \
-    strName = NULL;                                                                                          \
-}                                                                                                            \
-if(strType) {                                                                                                \
-    psFree(strType);                                                                                         \
-    strType = NULL;                                                                                          \
-}                                                                                                            \
-if(strValue) {                                                                                               \
-    psFree(strValue);                                                                                        \
-    strValue = NULL;                                                                                         \
-}                                                                                                            \
-if(strComment) {                                                                                             \
-    psFree(strComment);                                                                                      \
-    strComment = NULL;                                                                                       \
-}
-
-/** Maximum size of a FITS line */
-#define FITS_LINE_SIZE 80
-
-/** Maximum size of a string */
-#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);
-
-/** 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)
-{
-    char *ptrB = NULL;
-    char *ptrE = NULL;
-    char *cleaned = NULL;
-
-
-    ptrB = inString;
-
-    /* Skip over leading # or whitespace */
-    while (isspace(*ptrB) || *ptrB=='#') {
-        ptrB++;
-    }
-
-    /* Skip over trailing whitespace, null terminators, and # characters */
-    ptrE = inString + sLen;
-    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
-        ptrE--;
-    }
-
-    // Length, sLen, does not include '\0'
-    sLen = ptrE - ptrB + 1;
-
-    // Adds '\0' to end of string and +1 to sLen
-    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)
-{
-    char *cleanToken = NULL;
-    psS32 sLen = 0;
-
-
-    // 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);
-
-        // 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)
-{
-    char *end = NULL;
-    double value = 0.0;
-
-
-    value = strtod(inString, &end);
-    if(*end != '\0') {
-        *status = 1;
-    } else if(inString==end) {
-        *status = 1;
-    }
-
-    return value;
-}
-
-/** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */
-psBool parseBool(char *inString, psS32 *status)
-{
-    psBool value = false;
-
-
-    if(*inString=='T' || *inString=='t' || *inString=='1') {
-        value = true;
-    } else if(*inString=='F' || *inString=='f' || *inString=='0') {
-        value = false;
-    } else {
-        *status = 1;
-    }
-
-    return value;
-}
-
-/** Returns parsed vector filled with with data. The input string must be null terminated. */
-psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
-{
-    char *end = NULL;
-    char *saveValue = NULL;
-    psS32 i = 0;
-    psS32 numValues = 0;
-    double value = 0.0;
-    psVector *vec = NULL;
-
-
-    // Cycle through string and count entries
-    saveValue = inString;
-    while(*inString!='\0') {
-        strtod(inString, &end);
-        if(inString==end) {
-            *status = 1;
-            return NULL;
-        }
-        while(*end==' ' || *end==',') { // Commas or spaces may be used as delimiters for vector values
-            end++;
-        }
-        inString=end;
-        numValues++;
-    }
-
-    // Cycle through string and convert string values to values
-    if(numValues) {
-        inString = saveValue;
-        end = NULL;
-        vec = psVectorAlloc(numValues, elemType);
-
-        while(*inString!='\0') {
-            value = strtod(inString, &end);
-            if(inString==end) {
-                *status = 1;
-                return vec;
-            }
-            switch(elemType) {
-            case PS_TYPE_U8:
-                vec->data.U8[i++] = (psU8)value;
-                break;
-            case PS_TYPE_S32:
-                vec->data.S32[i++] = (psS32)value;
-                break;
-            case PS_TYPE_F32:
-                vec->data.F32[i++] = (psF32)value;
-                break;
-            case PS_TYPE_F64:
-                vec->data.F64[i++] = (psF64)value;
-                break;
-            default:
-                *status = 1;
-                psError(PS_ERR_BAD_PARAMETER_VALUE,true,
-                        PS_ERRORTEXT_psMetadataIO_TYPE_INVALID,
-                        elemType);
-            }
-
-            while(*end==' ' || *end==',') {
-                end++;
-            }
-            inString=end;
-        }
-    }
-
-    return vec;
-}
-
-/*****************************************************************************/
-/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
-/*****************************************************************************/
-
-bool psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* metadataItem)
-{
-    psMetadataType type;
-    psBool success = true;
-
-    PS_PTR_CHECK_NULL(fd, success);
-    PS_PTR_CHECK_NULL(format, success);
-    PS_PTR_CHECK_NULL(metadataItem, success);
-
-    type = metadataItem->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) metadataItem->data.B); \
-            break; \
-        case PS_META_S32: \
-            fprintf(fd,format,(FORMAT_TYPE)  metadataItem->data.S32); \
-            break; \
-        case PS_META_F32: \
-            fprintf(fd, format,(FORMAT_TYPE)  metadataItem->data.F32); \
-            break; \
-        case PS_META_F64: \
-            fprintf(fd, format,(FORMAT_TYPE) metadataItem->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*)metadataItem->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,metadataItem->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_PTR_CHECK_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;
-}
-
-psMetadata* psMetadataParseConfig(psMetadata* md, psU32 *nFail, const char *fileName, psBool overwrite)
-{
-    psBool tempBool;
-    char *line = NULL;
-    char *strName = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    char *strComment = NULL;
-    char *linePtr = NULL;
-    psElemType vecType = 0;
-    psS32 status = 0;
-    psU32 lineCount = 0;
-    psF64 tempDbl = 0.0;
-    psS32 tempInt = 0.0;
-    psVector *tempVec = NULL;
-    FILE *fp = NULL;
-    psMetadataType mdType;
-    psMetadataFlags flags;
-    psBool addStatus;
-
-    // Check for nulls
-    PS_PTR_CHECK_NULL(fileName,NULL);
-    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();
-    }
-
-    // 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++;
-        CLEAR_TEMPS();
-
-        // If line is not a comment or blank, then extract data
-        if(!ignoreLine(linePtr)) {
-
-            // Check for more than one '*' or '@' in a line
-            if(repeatedChars(linePtr, '@') > 1) {
-                (*nFail)++;
-                psError(PS_ERR_IO, true,
-                        PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);
-                continue;
-            } else if(repeatedChars(linePtr, '*') > 1) {
-                (*nFail)++;
-                psError(PS_ERR_IO, true,
-                        PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '*', lineCount, fileName);
-                continue;
-            } else if(repeatedChars(linePtr, '~') > 0) {
-                (*nFail)++;
-                psError(PS_ERR_IO, true,
-                        PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '~', lineCount, fileName);
-                continue;
-            }
-
-            // Get metadata item name
-            strName = getToken(&linePtr, " ", &status);
-            if(strName==NULL || status) {
-                (*nFail)++;
-                status = 0;
-                psError(PS_ERR_IO, true,
-                        PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "name", lineCount, fileName);
-                continue;
-            }
-
-            flags = (overwrite) ? PS_META_REPLACE : PS_META_DEFAULT;
-
-            // Get the metadata item type
-            strType = getToken(&linePtr, " ", &status);
-            if(strType==NULL) {
-                (*nFail)++;
-                status = 0;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,
-                        fileName);
-                continue;
-            } else {
-                char* tempStrType = strType;
-                if(*strType == '*') {
-                    flags = PS_META_DUPLICATE_OK;
-                    tempStrType = strType+1;
-                }
-
-                if(!strncmp(tempStrType, "STR", 3)) {
-                    mdType = PS_META_STR;
-                } else if(!strncmp(tempStrType, "BOOL", 4)) {
-                    mdType = PS_META_BOOL;
-                } else if(!strncmp(tempStrType, "S32", 3)) {
-                    mdType = PS_META_S32;
-                } else if(!strncmp(tempStrType, "F32", 3)) {
-                    mdType = PS_META_F32;
-                } else if(!strncmp(tempStrType, "F64", 3)) {
-                    mdType = PS_META_F64;
-                } else {
-                    (*nFail)++;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineCount,
-                            fileName);
-                    continue;
-                }
-            }
-
-            if(*strName == '@') {
-                vecType = PS_META_PRIMITIVE_TYPE(mdType);
-                mdType = PS_META_VEC;
-            }
-
-            // Get the metadata item value if there is one.
-            strValue = getToken(&linePtr, "#", &status);
-            if(status) {
-                (*nFail)++;
-                status = 0;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
-                        fileName);
-                continue;
-            }
-            if(strValue==NULL) {
-                (*nFail)++;
-                status = 0;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,
-                        fileName);
-                continue;
-            }
-
-            // Not all lines will have comments, so NULL is ok.
-            strComment = getToken(&linePtr,"~", &status);
-            if(status) {
-                (*nFail)++;
-                status = 0;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,
-                        fileName);
-                continue;
-            }
-
-            // Create and add metadata item to metadata and parse values
-            switch (mdType) {
-            case PS_META_STR:
-                addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
-                                          mdType | flags,
-                                          strComment, strValue);
-                break;
-            case PS_META_VEC:
-                tempVec = parseVector(strValue, vecType, &status);
-                if(!status) {
-                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName+1,
-                                              mdType | flags,
-                                              strComment, tempVec);
-                } else {
-                    status = 0;
-                    (*nFail)++;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
-                            strType, lineCount, fileName);
-                    continue;
-                }
-                psFree(tempVec);
-                break;
-            case PS_META_BOOL:
-                tempBool = parseBool(strValue, &status);
-                if(!status) {
-                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
-                                              mdType | flags,
-                                              strComment, tempBool);
-                } else {
-                    status = 0;
-                    (*nFail)++;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
-                            strType, lineCount, fileName);
-                    continue;
-                }
-                break;
-            case PS_META_S32:
-                tempInt = (psS32)parseValue(strValue, &status);
-                if(!status) {
-                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
-                                              mdType | flags,
-                                              strComment, tempInt);
-                } else {
-                    status = 0;
-                    (*nFail)++;
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName,
-                            strType, lineCount, fileName);
-                    continue;
-                }
-                break;
-            case PS_META_F32:
-            case PS_META_F64:
-                tempDbl = parseValue(strValue, &status);
-                if(!status) {
-                    addStatus = psMetadataAdd(md, PS_LIST_TAIL, strName,
-                                              mdType | flags,
-                                              strComment, tempDbl);
-                } else {
-                    status = 0;
-                    (*nFail)++;
-                    psError(PS_ERR_IO, true,
-                            PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, lineCount,
-                            fileName);
-                    continue;
-                }
-                break;
-            default:
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, mdType, lineCount,
-                        fileName);
-                continue;
-            } // switch
-            if (! addStatus) {
-                (*nFail)++;
-                psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineCount,
-                        fileName);
-            }
-
-        } // if ignoreLine
-    } // while loop
-
-    psFree(line);
-
-    return md;
-}
-
-static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
-{
-    psU64 i = 0;
-    char* psTagName = NULL;
-    char *psAttName = NULL;
-    char *psAttValue = NULL;
-    const xmlChar *attName = NULL;
-    const xmlChar *attValue = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_PTR_CHECK_NULL_GENERAL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_PTR_CHECK_NULL_GENERAL(input, return);
-
-    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-    psTagName = psStringCopy(tagName);
-
-    // Metadata containter for housing element attributes used by other SAX events
-    htAtts = psHashAlloc(10);
-
-
-    // Get tag name
-    if(psTagName != NULL) {
-        psHashAdd(htAtts, "tagName", psTagName);
-    } else {
-        PS_PTR_CHECK_NULL_GENERAL(psTagName, return);
-        psFree(htAtts);
-        psFree(psTagName);
-        return;
-    }
-
-    // Get all attribute names and attribute values
-    if(atts != NULL) {
-        attName = atts[i++];
-        attValue = atts[i++];
-        while(attName != NULL) {
-            if(attValue != NULL) {
-
-                // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-                psAttName = psStringCopy(attName);
-                psAttValue = psStringCopy(attValue);
-                psHashAdd(htAtts, psAttName, psAttValue);
-                psFree(psAttName);
-                psFree(psAttValue);
-            } else {
-                PS_PTR_CHECK_NULL_GENERAL(psAttValue, return);
-                psFree(htAtts);
-                psFree(psTagName);
-                return;
-            }
-            attName = atts[i++];
-            attValue = atts[i++];
-        }
-    }
-
-    // Add attributes to metadata
-
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
-                  PS_META_HASH | PS_META_DUPLICATE_OK,
-                  NULL, htAtts);
-
-    psFree(psTagName);
-    psFree(htAtts);
-
-    return;
-}
-
-static void initMetadataItemXml(void *ctx, char *tagName)
-{
-    psBool overwrite = false;
-    psBool tempBool = false;
-    psS32 status = 0;
-    psU32 lineNumber = 0;
-    psF64 tempDbl = 0.0;
-    psS32 tempInt = 0.0;
-    psMetadataType mdType = PS_META_UNKNOWN;
-    char *fileName = NULL;
-    char *strName = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    psMetadataItem *metadataItem = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_PTR_CHECK_NULL_GENERAL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_PTR_CHECK_NULL_GENERAL(input, return);
-    metadataItem = psMetadataLookup(md, "htAtts");
-    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
-    PS_PTR_CHECK_NULL_GENERAL(metadataItem->data.list, return);
-    metadataItem = (psMetadataItem*)psListGet(metadataItem->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)metadataItem->data.list;
-    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
-    fileName = (char*)input->filename;
-    PS_PTR_CHECK_NULL_GENERAL(fileName, return);
-    lineNumber = input->line;
-
-    // Get attribute name
-    strName = psHashLookup(htAtts, "name");
-    if(strName == NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
-        return;
-    }
-
-    // Get attribute type, if there is one
-    strType = psHashLookup(htAtts, "psType");
-    if(strType!= NULL) {
-        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psString")) {
-            mdType = PS_META_STR;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
-            mdType = PS_META_BOOL;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
-            mdType = PS_META_S32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
-            mdType = PS_META_F32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
-            mdType = PS_META_F64;
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strType, lineNumber,
-                    fileName);
-            return;
-        }
-    }
-
-    // Get attribute value, if there is one
-    strValue = psHashLookup(htAtts, "value");
-
-    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
-    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
-    found item is folder node, then psMetadataAdd will automatically add a new child. */
-    metadataItem = psMetadataLookup(md, "overwrite");
-    if(metadataItem != NULL) {
-        overwrite = parseBool((char*)strValue, &status);
-        if(status) {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        metadataItem = psMetadataLookup(md, strName);
-        if(metadataItem != NULL) {
-            if(metadataItem->type != PS_META_LIST) {
-                if(overwrite) {
-                    psMetadataRemove(md, INT_MIN, strName);
-                } else {
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
-                            fileName);
-                    return;
-                }
-            }
-        }
-    }
-
-    // Create metadata item and add to metadata
-    switch(mdType) {
-    case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName,
-                      mdType | PS_META_DUPLICATE_OK,
-                      NULL, NULL);
-        break;
-    case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName,
-                      mdType | PS_META_DUPLICATE_OK,
-                      NULL, strValue);
-        break;
-    case PS_META_BOOL:
-        tempBool = parseBool((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempBool);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        break;
-    case PS_META_S32:
-        tempInt = (psS32)parseValue((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempInt);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        break;
-    case PS_META_F32:
-    case PS_META_F64:
-        tempDbl = parseValue((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempDbl);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        break;
-    default:
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
-    } // End switch
-
-    return;
-}
-
-
-static void initVectorXml(void *ctx, char *tagName)
-{
-    bool overwrite = false;
-    psS32 status = 0;
-    psU32 lineNumber = 0;
-    psElemType pType = 0;
-    char *strName = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    char *fileName = NULL;
-    psMetadataItem *table = NULL;
-    psMetadataItem *tables = NULL;
-    psMetadataItem *metadataItem = NULL;
-    psVector *vec = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_PTR_CHECK_NULL_GENERAL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_PTR_CHECK_NULL_GENERAL(input, return);
-    tables = psMetadataLookup(md, "htAtts");
-    PS_PTR_CHECK_NULL_GENERAL(tables, return);
-    PS_PTR_CHECK_NULL_GENERAL(tables->data.list, return);
-    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)table->data.list;
-    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
-    fileName = (char*)input->filename;
-    PS_PTR_CHECK_NULL_GENERAL(fileName, return);
-    lineNumber = input->line;
-
-    // Get attribute name
-    strName = psHashLookup(htAtts, "name");
-    if(strName == NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
-        return;
-    }
-
-    // Get attribute type, if there is one
-    strType = psHashLookup(htAtts, "psType");
-    if(strType!= NULL) {
-        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
-            pType = PS_TYPE_U8;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
-            pType = PS_TYPE_S32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
-            pType = PS_TYPE_F32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
-            pType = PS_TYPE_F64;
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
-                    fileName);
-            return;
-        }
-    }
-
-    strValue = psHashLookup(htAtts, "value");
-    PS_PTR_CHECK_NULL_GENERAL(strValue, return);
-
-
-    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
-    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
-    found item is folder node, then psMetadataAdd will automatically add a new child. */
-    metadataItem = psMetadataLookup(md, "overwrite");
-    if(metadataItem != NULL) {
-        overwrite = parseBool((char*)strValue, &status);
-        if(status) {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    input->line, input->filename);
-        }
-        metadataItem = psMetadataLookup(md, strName);
-        if(metadataItem != NULL) {
-            if(metadataItem->type != PS_META_LIST) {
-                if(overwrite) {
-                    psMetadataRemove(md, INT_MIN, strName);
-                } else {
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
-                            fileName);
-                    return;
-                }
-            }
-        }
-    }
-
-    // Get value
-    vec = parseVector((char*)strValue, pType, &status);
-    if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
-                      PS_META_VEC | PS_META_DUPLICATE_OK,
-                      NULL, vec);
-    } else {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                lineNumber, fileName);
-    }
-    psFree(vec);
-}
-
-static void saxEndElement(void *ctx, const xmlChar *tagName)
-{
-    char *psStartTagName = NULL;
-    char *psEndTagName = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    psMetadataItem *table = NULL;
-    psMetadataItem *tables = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_PTR_CHECK_NULL_GENERAL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_PTR_CHECK_NULL_GENERAL(input, return);
-    tables = psMetadataLookup(md, "htAtts");
-    PS_PTR_CHECK_NULL_GENERAL(tables, return);
-    PS_PTR_CHECK_NULL_GENERAL(tables->data.list, return);
-    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)table->data.list;
-    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
-
-    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-    psEndTagName = psStringCopy(tagName);
-
-    // Compare start and end tag names
-    psStartTagName = psHashLookup(htAtts, "tagName");
-    PS_PTR_CHECK_NULL_GENERAL(psStartTagName, return);
-    if(strcmp(psEndTagName, psStartTagName)) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH, psStartTagName, psEndTagName);
-    }
-
-    // Initialize psLib structs
-    if(!strcmp(psEndTagName, "psMetadataItem")) {
-        initMetadataItemXml(ctx, psEndTagName);
-    } else if(!strcmp(psEndTagName, "psVector")) {
-        initVectorXml(ctx, psEndTagName);
-    } else if(strcmp(psEndTagName, "psRoot")) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN, psEndTagName);
-    }
-
-    // Free temporary metadata item and its hash table
-    psListRemove(tables->data.list, PS_LIST_TAIL);
-
-    psFree(psEndTagName);
-
-    return;
-}
-
-psMetadata*  psMetadataParseConfigXml(psMetadata* md, psU32 *nFail, const char *fileName, psBool overwrite)
-{
-    xmlSAXHandler saxHandler;
-
-
-    // Error checks
-    PS_PTR_CHECK_NULL(fileName, NULL);
-
-    // Allocate metadata if necessary
-    if (md == NULL) {
-        md = psMetadataAlloc();
-    }
-
-    // Sax handler initializations
-    saxHandler.internalSubset           = NULL;
-    saxHandler.isStandalone             = NULL;
-    saxHandler.hasInternalSubset        = NULL;
-    saxHandler.hasExternalSubset        = NULL;
-    saxHandler.resolveEntity            = NULL;
-    saxHandler.getEntity                = NULL;
-    saxHandler.entityDecl               = NULL;
-    saxHandler.notationDecl             = NULL;
-    saxHandler.attributeDecl            = NULL;
-    saxHandler.elementDecl              = NULL;
-    saxHandler.unparsedEntityDecl       = NULL;
-    saxHandler.setDocumentLocator       = NULL;
-    saxHandler.startDocument            = NULL;
-    saxHandler.endDocument              = NULL;
-    saxHandler.startElement             = saxStartElement;
-    saxHandler.endElement               = saxEndElement;
-    saxHandler.reference                = NULL;
-    saxHandler.characters               = NULL;
-    saxHandler.ignorableWhitespace      = NULL;
-    saxHandler.processingInstruction    = NULL;
-    saxHandler.comment                  = NULL;
-    saxHandler.warning                  = xmlParserError;
-    saxHandler.error                    = xmlParserError;
-    saxHandler.fatalError               = xmlParserError;
-    saxHandler.getParameterEntity       = NULL;
-    saxHandler.cdataBlock               = NULL;
-    saxHandler.externalSubset           = NULL;
-    saxHandler.initialized              = 1;
-    saxHandler._private                 = md;
-    saxHandler.startElementNs           = NULL;
-    saxHandler.endElementNs             = NULL;
-    saxHandler.serror                   = NULL;
-
-    // Parse XML file
-    if (xmlSAXUserParseFile(&saxHandler, NULL, fileName)) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
-        return NULL;
-    }
-
-    // Parser and memory cleanups for libxml2
-    xmlCleanupParser();
-    xmlMemoryDump();
-
-    return md;
-}
Index: trunk/psLib/src/astronomy/psMetadataIO.h
===================================================================
--- trunk/psLib/src/astronomy/psMetadataIO.h	(revision 3690)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/** @file  psMetadataIO.h
- *
- *  @brief Contains metadata input/output functions.
- *
- *  This file defines functions to read and write metadata to/from an external file.
- *
- *  @ingroup Metadata
- *
- *  @author Ross Harman, MHPCC
- *  @author Robert DeSonia, MHPCC
- *
- *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-03-07 20:58:50 $
- *
- *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
- */
-#ifndef PS_METADATAIO_H
-#define PS_METADATAIO_H
-
-/// @addtogroup Metadata
-/// @{
-
-
-/** Print metadata item to file.
- *
- *  Metadata items may be printed to an open file descriptor based on a
- *  provided format. The format is a sprintf format statement with exactly
- *  one % formatting command. If the metadata item type is a numeric type,
- *  this formatting command must also be numeric, and the type conversion
- *  performed to the value to match the format type. If the metadata type is
- *  a string, the fromatting command must also be for a string. If the
- *  metadata type is any other data type, printing is not allowed.
- *
- * @return psMetadataItem* : Pointer metadata item.
- */
-bool psMetadataItemPrint(
-    FILE * fd,                         ///< Pointer to file to write metadata item.
-    const char *format,                ///< Format to print metadata item.
-    const psMetadataItem* metadataItem ///< Metadata item to print.
-);
-
-/** Read metadata header.
- *
- *  Read a metadata header from file. If the file is not found, an error is
- *  reported.
- *
- *  @return psMetadata* : Pointer to resulting metadata.
- */
-psMetadata* psMetadataReadHeader(
-    psMetadata* output,                ///< Resulting metadata from read.
-    char *extName,                     ///< File name extension string.
-    psS32 extNum,                      ///< File name extension number. Starts at 1.
-    char *fileName                     ///< Name of file to read.
-);
-
-/** Read metadata configuration file.
- *
- *  Loads pre-defined settings by parsing a configuration file into a psMetadata structure.
- *
- *  @return psMetadata* : Resulting metadata from read.
- */
-psMetadata* psMetadataParseConfig(
-    psMetadata* md,                    ///< Resulting metadata from read.
-    psU32 *nFail,                      ///< Number of failed lines.
-    const char *fileName,              ///< Name of file to read.
-    psBool overwrite                   ///< Allow overwrite of duplicate specifications.
-);
-
-/** Read XML metadata configuration file.
- *
- *  Loads pre-defined XML settings by parsing a configuration file into a psMetadata structure.
- *
- *  @return psMetadata* : Resulting metadata from read.
- */
-
-psMetadata*  psMetadataParseConfigXml(
-    psMetadata* md,                    ///< Resulting metadata from read.
-    psU32 *nFail,                      ///< Number of failed lines.
-    const char *fileName,              ///< Name of file to read.
-    psBool overwrite                   ///< Allow overwrite of duplicate specifications.
-);
-
-/// @}
-
-#endif
