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
Index: trunk/psLib/src/fileUtils/.cvsignore
===================================================================
--- trunk/psLib/src/fileUtils/.cvsignore	(revision 3690)
+++ 	(revision )
@@ -1,7 +1,0 @@
-Makefile.in
-.deps
-.libs
-Makefile
-*.lo
-*.la
-
Index: trunk/psLib/src/fileUtils/Makefile.am
===================================================================
--- trunk/psLib/src/fileUtils/Makefile.am	(revision 3690)
+++ 	(revision )
@@ -1,30 +1,0 @@
-#Makefile for dataIO functions of psLib
-#
-INCLUDES = \
-	-I$(top_srcdir)/src/astronomy \
-	-I$(top_srcdir)/src/collections \
-	-I$(top_srcdir)/src/dataManip \
-	-I$(top_srcdir)/src/image \
-	-I$(top_srcdir)/src/sysUtils \
-	$(all_includes)
-
-noinst_LTLIBRARIES = libpslibdataIO.la
-
-libpslibdataIO_la_SOURCES = \
-	psLookupTable.c \
-	psFits.c \
-	psDB.c
-
-
-BUILT_SOURCES = psFileUtilsErrors.h
-EXTRA_DIST = psFileUtilsErrors.dat psFileUtilsErrors.h dataIO.i
-
-psFileUtilsErrors.h: psFileUtilsErrors.dat
-	perl $(top_srcdir)/src/parseErrorCodes.pl --data=$? $@
-
-pslibincludedir = $(includedir)
-pslibinclude_HEADERS = \
-	psLookupTable.h \
-	psFits.h \
-	psDB.h
-
Index: trunk/psLib/src/fileUtils/fileUtils.i
===================================================================
--- trunk/psLib/src/fileUtils/fileUtils.i	(revision 3690)
+++ 	(revision )
@@ -1,4 +1,0 @@
-/* dataIO headers */
-%include "psFileUtilsErrors.h"
-%include "psFits.h"
-%include "psLookupTable.h"
Index: trunk/psLib/src/fileUtils/psDB.c
===================================================================
--- trunk/psLib/src/fileUtils/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/fileUtils/psDB.h
===================================================================
--- trunk/psLib/src/fileUtils/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/fileUtils/psFileUtilsErrors.dat
===================================================================
--- trunk/psLib/src/fileUtils/psFileUtilsErrors.dat	(revision 3690)
+++ 	(revision )
@@ -1,58 +1,0 @@
-#
-#  This file is used to generate psFileUtilsErrors.h content
-#
-#  Format is:
-#  ERRORNAME(one word)    ERROR_TEXT
-#
-#  N.B. in code, the ERRORNAME appears as PS_ERRORTEXT_ERRORNAME
-####################################################################
-psLookupTable_FILE_NOT_FOUND           Failed to open file %s.
-psLookupTable_PARSE_VALUE              Unable to parse string, %s on line %lld.
-psLookupTable_PARSE_TYPE               Unable to parse type, %s on line %lld.
-psLookupTable_PARSE_GENERAL            Unable to read lookup table item, %s on line %lld
-psLookupTable_INTERPOLATE_HIGH         High index too big, %d.
-psLookupTable_INTERPOLATE_LOW          Low index too small, %d.
-psLookupTable_DIVIDE_BY_ZERO           Divide by zero error during interpolation.
-psLookupTable_INVALID_TYPE             Invalid psLookupType, %d;
-psLookupTable_TABLE_INVALID            Lookup table is invalid.
-#
-psFits_NULL                            The input psFits object can not NULL.
-psFits_FILENAME_INVALID                Could not open file,'%s'.\nCFITSIO Error: %s
-psFits_FILENAME_NULL                   Specified filename can not be NULL.
-psFits_EXTNAME_NULL                    Specified extension name can not be NULL.
-psFits_EXTNAME_INVALID                 Could not find HDU '%s' in file %s.\nCFITSIO Error: %s
-psFits_EXTNUM_ABS_MOVE_FAILED          Could not move to specified HDU #%d in file %s.\nCFITSIO Error: %s
-psFits_EXTNUM_REL_MOVE_FAILED          Could not move %d HDUs from current position in file %s.\nCFITSIO Error: %s
-psFits_GET_EXTNUM_FAILED               Failed to determine the current HDU number in file %s.\nCFITSIO Error: %s
-psFits_GETNUMHDUS_FAILED               Failed to determine the number of HDUs in file %s.\nCFITSIO Error: %s
-psFits_GETHDUTYPE_FAILED               Failed to determine an HDU type in file %s.\nCFITSIO Error: %s
-psFits_GETNUMKEYS_FAILED               Failed to determine the number of header keys in file %s.\nCFITSIO Error: %s
-psFits_GET_TABLE_SIZE_FAILED           Failed to determine the size of the current HDU table.\nCFITSIO Error: %s
-psFits_FILENAME_CREATE_FAILED          Could not create file,'%s'.\nCFITSIO Error: %s
-psFits_TYPE_UNSUPPORTED                Specified type, %s, is not supported.
-psFits_CREATE_HDU_FAILED               Could not create new image HDU in file,'%s'.\nCFITSIO Error: %s
-psFits_GET_HDU_TYPE_FAILED             Could not determine the HDU type.\nCFITSIO Error: %s
-psFits_NOT_IMAGE_TYPE                  Current FITS HDU type must be an image.
-psFits_NOT_TABLE_TYPE                  Current FITS HDU type must be a table.
-psFits_TABLE_EMPTY                     Can't create a table without any rows.
-psFits_CFITSIO_ERROR                   CFITSIO error: %s
-psFits_METATYPE_INVALID                Specified FITS metadata type, %c, is not supported.
-psFits_METADATA_ADD_FAILED             Failed to add metadata item, %s.
-psFits_WRITE_FAILED                    Could not write data to file,'%s'.\nCFITSIO Error: %s
-psFits_IMAGE_NULL                      The input psImage was NULL.  Need a non-NULL psImage for operation to be performed.
-psFits_METADATA_NULL                   The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed.
-psFits_METADATA_PTYPE_UNSUPPORTED      A metadata item's primative type, %d, is not supported.
-psFits_ROW_INVALID                     Specified row, %d, is not valid for current table of %d rows.
-psFits_GET_TABLE_ELEMENT               Failed to retrieve table element (%d,%d).\nCFITSIO Error: %s
-psFits_FIND_COLUMN                     Specified column, %s, was not found.\nCFITSIO Error: %s
-psFits_GET_COLTYPE                     Could not determine the datatype of the table column.\nCFITSIO Error: %s
-psFits_TABLE_READ_COL                  Failed to read table column.\nCFITSIO Error: %s
-psFits_DATATYPE_UNKNOWN                Could not determine image data type.\nCFITSIO Error: %s
-psFits_IMAGE_DIM_UNKNOWN               Could not determine image dimensions.\nCFITSIO Error: %s
-psFits_IMAGE_DIMENSION_UNSUPPORTED     Image number of dimensions, %d, is not valid.  Only two or three dimensions supported for FITS I/O.
-psFits_IMAGE_SIZE_UNKNOWN              Could not determine image size.\nCFITSIO Error: %s
-psFits_FITS_TYPE_UNSUPPORTED           FITS image type, BITPIX=%d, is not supported.
-psFits_READ_FAILED                     Reading FITS file failed.\nCFITSIO Error: %s
-psFits_IMAGE_UPDATE_TYPE_MISMATCH      Can not update a %s image given a %s image.
-psFits_FITS_Z_SMALL                    Current FITS HDU has %d z-planes, but z-plane %d was specified.
-#
Index: trunk/psLib/src/fileUtils/psFileUtilsErrors.h
===================================================================
--- trunk/psLib/src/fileUtils/psFileUtilsErrors.h	(revision 3690)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/** @file  psFileUtilsErrors.h
- *
- *  @brief Contains the error text for the dataIO functions
- *
- *  @ingroup ErrorHandling
- *
- *  @author Robert DeSonia, MHPCC
- *
- *  @version $Revision: 1.13 $ $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_FILEUTIL_ERRORS_H
-#define PS_FILEUTIL_ERRORS_H
-
-/* N.B., lines between '//~Start' and '//~End' are automatic generated from
- * the template following the '//~Start'.  The template is used to generate
- * the other lines by, for each error text in psAstronomyErrors.dat, the following
- * substitutions are made:
- *     $1  The error text macro name (first word in the psAstronomyErrors.dat lines)
- *     $2  The error text (rest of the line in psAstronomyErrors.dat)
- *     $n  The order of the source line in psAstronomyErrors.dat (comments excluded)
- * 
- * DO NOT EDIT THE LINES BETWEEN //~Start and //~End!  ANY CHANGES WILL BE OVERWRITTEN.
- */
-
-//~Start #define PS_ERRORTEXT_$1 "$2"
-#define PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND "Failed to open file %s."
-#define PS_ERRORTEXT_psLookupTable_PARSE_VALUE "Unable to parse string, %s on line %lld."
-#define PS_ERRORTEXT_psLookupTable_PARSE_TYPE "Unable to parse type, %s on line %lld."
-#define PS_ERRORTEXT_psLookupTable_PARSE_GENERAL "Unable to read lookup table item, %s on line %lld"
-#define PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH "High index too big, %d."
-#define PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW "Low index too small, %d."
-#define PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO "Divide by zero error during interpolation."
-#define PS_ERRORTEXT_psLookupTable_INVALID_TYPE "Invalid psLookupType, %d;"
-#define PS_ERRORTEXT_psLookupTable_TABLE_INVALID "Lookup table is invalid."
-#define PS_ERRORTEXT_psFits_NULL "The input psFits object can not NULL."
-#define PS_ERRORTEXT_psFits_FILENAME_INVALID "Could not open file,'%s'.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_FILENAME_NULL "Specified filename can not be NULL."
-#define PS_ERRORTEXT_psFits_EXTNAME_NULL "Specified extension name can not be NULL."
-#define PS_ERRORTEXT_psFits_EXTNAME_INVALID "Could not find HDU '%s' in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_EXTNUM_ABS_MOVE_FAILED "Could not move to specified HDU #%d in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_EXTNUM_REL_MOVE_FAILED "Could not move %d HDUs from current position in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GET_EXTNUM_FAILED "Failed to determine the current HDU number in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED "Failed to determine the number of HDUs in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED "Failed to determine an HDU type in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GETNUMKEYS_FAILED "Failed to determine the number of header keys in file %s.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED "Failed to determine the size of the current HDU table.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED "Could not create file,'%s'.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED "Specified type, %s, is not supported."
-#define PS_ERRORTEXT_psFits_CREATE_HDU_FAILED "Could not create new image HDU in file,'%s'.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED "Could not determine the HDU type.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE "Current FITS HDU type must be an image."
-#define PS_ERRORTEXT_psFits_NOT_TABLE_TYPE "Current FITS HDU type must be a table."
-#define PS_ERRORTEXT_psFits_TABLE_EMPTY "Can't create a table without any rows."
-#define PS_ERRORTEXT_psFits_CFITSIO_ERROR "CFITSIO error: %s"
-#define PS_ERRORTEXT_psFits_METATYPE_INVALID "Specified FITS metadata type, %c, is not supported."
-#define PS_ERRORTEXT_psFits_METADATA_ADD_FAILED "Failed to add metadata item, %s."
-#define PS_ERRORTEXT_psFits_WRITE_FAILED "Could not write data to file,'%s'.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_IMAGE_NULL "The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."
-#define PS_ERRORTEXT_psFits_METADATA_NULL "The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed."
-#define PS_ERRORTEXT_psFits_METADATA_PTYPE_UNSUPPORTED "A metadata item's primative type, %d, is not supported."
-#define PS_ERRORTEXT_psFits_ROW_INVALID "Specified row, %d, is not valid for current table of %d rows."
-#define PS_ERRORTEXT_psFits_GET_TABLE_ELEMENT "Failed to retrieve table element (%d,%d).\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_FIND_COLUMN "Specified column, %s, was not found.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_GET_COLTYPE "Could not determine the datatype of the table column.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_TABLE_READ_COL "Failed to read table column.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_DATATYPE_UNKNOWN "Could not determine image data type.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_IMAGE_DIM_UNKNOWN "Could not determine image dimensions.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_IMAGE_DIMENSION_UNSUPPORTED "Image number of dimensions, %d, is not valid.  Only two or three dimensions supported for FITS I/O."
-#define PS_ERRORTEXT_psFits_IMAGE_SIZE_UNKNOWN "Could not determine image size.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_FITS_TYPE_UNSUPPORTED "FITS image type, BITPIX=%d, is not supported."
-#define PS_ERRORTEXT_psFits_READ_FAILED "Reading FITS file failed.\nCFITSIO Error: %s"
-#define PS_ERRORTEXT_psFits_IMAGE_UPDATE_TYPE_MISMATCH "Can not update a %s image given a %s image."
-#define PS_ERRORTEXT_psFits_FITS_Z_SMALL "Current FITS HDU has %d z-planes, but z-plane %d was specified."
-//~End
-
-#endif
Index: trunk/psLib/src/fileUtils/psFits.c
===================================================================
--- trunk/psLib/src/fileUtils/psFits.c	(revision 3690)
+++ 	(revision )
@@ -1,1695 +1,0 @@
-/** @file  psFits.c
- *
- *  @brief Contains Fits I/O routines
- *
- *  @ingroup FileIO
- *
- *  @author Robert DeSonia, MHPCC
- *
- *  @version $Revision: 1.27 $ $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 <unistd.h>
-
-#include "psFits.h"
-#include "string.h"
-#include "psError.h"
-#include "psFileUtilsErrors.h"
-#include "psImageExtraction.h"
-#include "psMemory.h"
-#include "psString.h"
-#include "psLogMsg.h"
-#include "psTrace.h"
-
-#define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
-
-// list of FITS header keys to ignore.
-static char* standardFitsKeys[] = {
-                                      NULL
-                                  };
-
-static psElemType convertFitsToPsType(int datatype)
-{
-    switch (datatype) {
-    case TBYTE:
-        return PS_TYPE_U8;
-    case TSBYTE:
-        return PS_TYPE_S8;
-    case TSHORT:
-        return PS_TYPE_S16;
-    case TUSHORT:
-        return PS_TYPE_U16;
-    case TLONG:
-        if (sizeof(long) == 8) {
-            return PS_TYPE_S64;
-        }
-        // no break
-    case TINT:
-        return PS_TYPE_S32;
-    case TULONG:
-        if (sizeof(unsigned long) == 8) {
-            return PS_TYPE_U64;
-        }
-        // no break
-    case TUINT:
-        return PS_TYPE_U32;
-    case TLONGLONG:
-        return PS_TYPE_S64;
-    case TFLOAT:
-        return PS_TYPE_F32;
-    case TDOUBLE:
-        return PS_TYPE_F64;
-    case TCOMPLEX:
-        return PS_TYPE_C32;
-    case TDBLCOMPLEX:
-        return PS_TYPE_C64;
-    case TLOGICAL:
-        return PS_TYPE_BOOL;
-    default:
-        psError(PS_ERR_IO, true,
-                "Unknown FITS datatype, %d.",
-                datatype);
-        return 0;
-    }
-}
-
-static bool convertPsTypeToFits(psElemType type, int* bitPix, double* bZero, int* dataType)
-{
-
-    int bitpix;
-    int datatype;
-    double bzero = 0.0;
-
-    switch (type) {
-
-    case PS_TYPE_U8:
-        bitpix = BYTE_IMG;
-        datatype = TBYTE;
-        break;
-
-    case PS_TYPE_BOOL:
-    case PS_TYPE_S8:
-        bitpix = BYTE_IMG;
-        bzero = INT8_MIN;
-        datatype = TSBYTE;
-        break;
-
-    case PS_TYPE_U16:
-        bitpix = SHORT_IMG;
-        bzero = -1.0 * INT16_MIN;
-        datatype = TUSHORT;
-        break;
-
-    case PS_TYPE_S16:
-        bitpix = SHORT_IMG;
-        datatype = TSHORT;
-        break;
-
-    case PS_TYPE_U32:
-        bitpix = LONG_IMG;
-        bzero = -1.0 * INT32_MIN;
-        datatype = TUINT;
-        break;
-
-    case PS_TYPE_S32:
-        bitpix = LONG_IMG;
-        datatype = TINT;
-        break;
-
-    case PS_TYPE_F32:
-        bitpix = FLOAT_IMG;
-        datatype = TFLOAT;
-        break;
-
-    case PS_TYPE_F64:
-        bitpix = DOUBLE_IMG;
-        datatype = TDOUBLE;
-        break;
-
-    default: {
-            char* typeStr;
-            PS_TYPE_NAME(typeStr,type);
-            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
-                    PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED,
-                    typeStr);
-            return false;
-        }
-    }
-
-    // pass the requested parameters  (NULL parameters are not set, of course).
-    if (bitPix != NULL) {
-        *bitPix = bitpix;
-    }
-
-    if (dataType != NULL) {
-        *dataType = datatype;
-    }
-
-    if (bZero != NULL) {
-        *bZero = bzero;
-    }
-
-    return true;
-}
-
-static bool convertMetadataTypeToBinaryTForm(psMetadataType type, char** fitsType)
-{
-    switch (type) {
-    case PS_META_BOOL:
-        *fitsType = psStringCopy("1L");
-        break;
-    case PS_META_S32:
-        *fitsType = psStringCopy("1J");
-        break;
-    case PS_META_F32:
-        *fitsType = psStringCopy("1E");
-        break;
-    case PS_META_F64:
-        *fitsType = psStringCopy("1D");
-        break;
-        // XXX: Handle other types, e.g., Vectors, etc.
-    default:
-        return false;
-    }
-
-    return true;
-}
-
-static bool isHDUEmpty(const psFits* fits)
-{
-    /* check for keys - no keys means this is really an empty HDU */
-    int keysexist = -1;
-    int morekeys;
-    int status = 0;
-
-    fits_get_hdrspace(fits->p_fd, &keysexist, &morekeys, &status);
-
-    // if no keys exist and not primary HDU, this really is an empty HDU
-    if (keysexist == 0) {
-        return true;
-    }
-
-    return false;
-
-}
-
-static void fitsFree(psFits* fits)
-{
-    int status = 0;
-
-    if (fits != NULL) {
-        (void)fits_close_file(fits->p_fd, &status);
-        psFree((void*)fits->filename);
-    }
-}
-
-psFits* psFitsAlloc(const char* name)
-{
-    int status = 0;
-    fitsfile *fptr = NULL;      /* Pointer to the FITS file */
-
-    if (name == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_FILENAME_NULL);
-        return NULL;
-    }
-
-    /* Open/Create the FITS file */
-    if (access(name, F_OK) == 0) {     // file exists
-        (void)fits_open_file(&fptr, name, READWRITE, &status);
-        if (fptr == NULL) { // if failed, try openning as just read-only
-            status = 0;
-            (void)fits_open_file(&fptr, name, READONLY, &status);
-        }
-        if (fptr == NULL || status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    PS_ERRORTEXT_psFits_FILENAME_INVALID,
-                    name, fitsErr);
-            return NULL;
-        }
-    } else {  // file does not exist, so create.
-        (void)fits_create_file(&fptr, name, &status);
-        if (fptr == NULL || status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED,
-                    name, fitsErr);
-            return NULL;
-        }
-    }
-
-    psFits* fits = psAlloc(sizeof(psFits));
-    fits->filename = psAlloc(strlen(name)+1);
-    fits->p_fd = fptr;
-    strcpy((char*)fits->filename,name);
-    psMemSetDeallocator(fits,(psFreeFcn)fitsFree);
-
-    return fits;
-}
-
-bool psFitsMoveExtName(const psFits* fits,
-                       const char* extname)
-{
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (extname == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_EXTNAME_NULL);
-        return false;
-    }
-
-
-    if (fits_movnam_hdu(fits->p_fd, ANY_HDU, (char*)extname, 0, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_LOCATION_INVALID, true,
-                PS_ERRORTEXT_psFits_EXTNAME_INVALID,
-                extname, fits->filename, fitsErr);
-        return false;
-    }
-
-    return true;
-}
-
-bool psFitsMoveExtNum(const psFits* fits,
-                      int extnum,
-                      bool relative)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    int status = 0;
-    int hdutype = 0;
-
-    if (relative) {
-        fits_movrel_hdu(fits->p_fd, extnum, &hdutype, &status);
-        if (status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_LOCATION_INVALID, true,
-                    PS_ERRORTEXT_psFits_EXTNUM_REL_MOVE_FAILED,
-                    extnum, fits->filename, fitsErr);
-            return false;
-        }
-    } else {
-        fits_movabs_hdu(fits->p_fd, extnum+1, &hdutype, &status);
-        if (status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_LOCATION_INVALID, true,
-                    PS_ERRORTEXT_psFits_EXTNUM_ABS_MOVE_FAILED,
-                    extnum, fits->filename, fitsErr);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-int psFitsGetExtNum(const psFits* fits)
-{
-    int hdunum;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return PS_FITS_TYPE_NONE;
-    }
-
-
-    return fits_get_hdu_num(fits->p_fd,&hdunum) - 1;
-}
-
-char* psFitsGetExtName(const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    int status = 0;
-    char name[MAX_STRING_LENGTH];
-
-    if (fits_read_key_str(fits->p_fd, "EXTNAME", name, NULL, &status) != 0) {
-        status = 0;
-        if (fits_read_key_str(fits->p_fd, "HDUNAME", name, NULL, &status) != 0) {
-            int num = psFitsGetExtNum(fits);
-            snprintf(name, MAX_STRING_LENGTH, "EXT-%3d",num);
-        }
-    }
-    return psStringCopy(name);
-}
-
-bool psFitsSetExtName(const psFits* fits, const char* name)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (name == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_EXTNAME_NULL);
-        return false;
-    }
-
-    int status = 0;
-
-    if (fits_update_key_str(fits->p_fd, "EXTNAME", (char*)name, NULL, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_WRITE_FAILED,
-                fits->filename, fitsErr);
-        return false;
-    }
-
-    return true;
-}
-
-int psFitsGetSize(const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return 0;
-    }
-
-    int num = 0;
-    int status = 0;
-
-    if (fits_get_num_hdus(fits->p_fd, &num, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_LOCATION_INVALID, true,
-                PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED,
-                fits->filename, fitsErr);
-        return 0;
-    }
-
-    return num;
-}
-
-psFitsType psFitsGetExtType(const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return PS_FITS_TYPE_NONE;
-    }
-
-    int status = 0;
-    int hdutype = PS_FITS_TYPE_NONE;
-
-    if (fits_get_hdu_type(fits->p_fd, &hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_LOCATION_INVALID, true,
-                PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED,
-                fits->filename, fitsErr);
-        return PS_FITS_TYPE_NONE;
-    }
-
-    if (hdutype == PS_FITS_TYPE_IMAGE &&
-            psFitsGetExtNum(fits) > 0 &&
-            isHDUEmpty(fits)) {
-        return PS_FITS_TYPE_ANY;
-    }
-
-    return hdutype;
-}
-
-psMetadata* psFitsReadHeader(psMetadata* out,
-                             const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    if (out == NULL) {
-        out = psMetadataAlloc();
-        if (out == NULL) {
-            psError(PS_ERR_UNKNOWN, false,
-                    "Failed to allocate a new psMetadata container.");
-            return NULL;
-        }
-    }
-
-    // Get number of key names
-    int numKeys = 0;
-    int keyNum = 0;
-    int status = 0;
-    fits_get_hdrpos(fits->p_fd, &numKeys, &keyNum, &status);
-
-    // Get each key name. Keywords start at one.
-    char keyType;
-    char keyName[MAX_STRING_LENGTH];
-    char keyValue[MAX_STRING_LENGTH];
-    char keyComment[MAX_STRING_LENGTH];
-    psBool tempBool;
-    psBool success;
-    psBool stdKey;
-    for (int i = 1; i <= numKeys; i++) {
-
-        fits_read_keyn(fits->p_fd, i, keyName, keyValue, keyComment, &status);
-
-        stdKey = false;
-
-        int stdKeyIdx = 0;
-        while (standardFitsKeys[stdKeyIdx] != NULL && ! stdKey) {
-            if (strcmp(keyName,standardFitsKeys[stdKeyIdx++]) == 0) {
-                stdKey = true;
-            }
-        }
-
-        if (keyValue[0] != 0) { // blank values are not handled by fits_get_keytype
-            fits_get_keytype(keyValue, &keyType, &status);
-        } else {
-            keyType = 'C';
-        }
-        if (status != 0) {
-            break;
-        }
-
-        if (! stdKey) {
-            switch (keyType) {
-            case 'X': // bit
-            case 'I': // short int.
-            case 'J': // int.
-            case 'B': // byte
-                success = psMetadataAdd(out,
-                                        PS_LIST_TAIL,
-                                        keyName,
-                                        PS_META_S32 | PS_META_DUPLICATE_OK,
-                                        keyComment,
-                                        atoi(keyValue));
-                break;
-            case 'U': // unsigned int. may not fit in a psS32
-            case 'K': // long int. can't all fit in a psS32
-            case 'F':
-                success = psMetadataAdd(out,
-                                        PS_LIST_TAIL,
-                                        keyName,
-                                        PS_META_F64 | PS_META_DUPLICATE_OK,
-                                        keyComment,
-                                        atof(keyValue));
-                break;
-            case 'C':
-                // remove the single-quotes at front/end
-                if (keyValue[0] == '\'' && keyValue[strlen(keyValue)-1] == '\'') {
-                    keyValue[strlen(keyValue)-1] = '\0';
-                    success = psMetadataAdd(out,
-                                            PS_LIST_TAIL,
-                                            keyName,
-                                            PS_META_STR | PS_META_DUPLICATE_OK,
-                                            keyComment,
-                                            keyValue+1);
-                } else {
-                    success = psMetadataAdd(out,
-                                            PS_LIST_TAIL,
-                                            keyName,
-                                            PS_META_STR | PS_META_DUPLICATE_OK,
-                                            keyComment,
-                                            keyValue);
-                }
-                break;
-            case 'L':
-                tempBool = (keyValue[0] == 'T') ? 1 : 0;
-                success = psMetadataAdd(out,
-                                        PS_LIST_TAIL,
-                                        keyName,
-                                        PS_META_BOOL | PS_META_DUPLICATE_OK,
-                                        keyComment,
-                                        tempBool);
-                break;
-            default:
-                psError(PS_ERR_IO, true,
-                        PS_ERRORTEXT_psFits_METATYPE_INVALID,
-                        keyType);
-                return out;
-            }
-
-            if (!success) {
-                psError(PS_ERR_UNKNOWN, false,
-                        PS_ERRORTEXT_psFits_METADATA_ADD_FAILED,
-                        keyName);
-                return out;
-            }
-        }
-
-    }
-
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_METADATA_ADD_FAILED,
-                fitsErr);
-        return false;
-    }
-
-    return out;
-}
-
-psHash* psFitsReadHeaderSet(psHash* out,
-                            const psFits* fits)
-{
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        psFree(out);
-        return NULL;
-    }
-
-    if (out == NULL) {
-        out = psHashAlloc(10);
-        // XXX: what is the appropriate number of buckets? Got 10 from psMetadataAlloc.
-        if (out == NULL) {
-            psError(PS_ERR_UNKNOWN, false,
-                    "Failed to allocate a new psHash container.");
-            return NULL;
-        }
-    }
-
-    int size = psFitsGetSize(fits);
-
-    int origPosition = psFitsGetExtNum(fits);
-
-    for (int lcv=0; lcv < size; lcv++) {
-        psFitsMoveExtNum(fits, lcv, false);
-
-        char* name = NULL;
-        if (lcv == 0) {
-            name = psStringCopy("PHU");
-        } else {
-            name = psFitsGetExtName(fits);
-        }
-
-        psMetadata* header = psFitsReadHeader(NULL, fits);
-        if (name != NULL && header != NULL) {
-            psHashAdd(out, name, header);
-        } else { // XXX: is this a warning or error?
-            psLogMsg(__func__, PS_LOG_WARN,
-                     "Failed to read HDU#%d header data.",
-                     lcv);
-        }
-
-        psFree(name);
-        psFree(header);
-    }
-
-    // reposition to the original position
-    psFitsMoveExtNum(fits, origPosition, false);
-
-    return out;
-}
-
-psImage* psFitsReadImage(psImage* output, // a psImage to recycle.
-                         const psFits* fits,    // the psFits object
-                         psRegion region, // the region in the FITS image to read
-                         int z)           // the z-plane in the FITS image cube to read
-{
-    psS32 status = 0;           /* CFITSIO file vars */
-    psS32 nAxis = 0;
-    psS32 anynull = 0;
-    psS32 bitPix = 0;           /* Pixel type */
-    long nAxes[3];
-    long firstPixel[3];         /* lower-left corner of image subset */
-    long lastPixel[3];          /* upper-right corner of image subset */
-    long increment[3];          /* increment for image subset */
-    char fitsErr[80] = "";      /* CFITSIO error message string */
-    psS32 fitsDatatype = 0;
-    psS32 datatype = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        psFree(output);
-        return NULL;
-    }
-
-    // check to see if we even are positioned on an image HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != IMAGE_HDU) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE);
-        return NULL;
-    }
-
-    /* Get the data type 'bitPix' from the FITS image */
-    if (fits_get_img_equivtype(fits->p_fd, &bitPix, &status) != 0) {
-        fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_DATATYPE_UNKNOWN,
-                fitsErr);
-        psFree(output);
-        return NULL;
-    }
-
-    /* Get the dimensions 'nAxis' from the FITS image */
-    if (fits_get_img_dim(fits->p_fd, &nAxis, &status) != 0) {
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_IMAGE_DIM_UNKNOWN,
-                fitsErr);
-        psFree(output);
-        return NULL;
-    }
-
-    /* Validate the number of axis */
-    if ((nAxis < 2) || (nAxis > 3)) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_IMAGE_DIMENSION_UNSUPPORTED,
-                nAxis);
-        psFree(output);
-        return NULL;
-    }
-
-    /* Get the Image size from the FITS file */
-    if (fits_get_img_size(fits->p_fd, nAxis, nAxes, &status) != 0) {
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_IMAGE_SIZE_UNKNOWN,
-                fitsErr);
-        psFree(output);
-        return NULL;
-    }
-
-    firstPixel[0] = region.x0 + 1;
-    firstPixel[1] = region.y0 + 1;
-    firstPixel[2] = z + 1;
-
-    if (region.x1 > 0) {
-        lastPixel[0] = region.x1;
-    } else {
-        lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0
-    }
-    if (region.y1 > 0) {
-        lastPixel[1] = region.y1;
-    } else {
-        lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0
-    }
-    lastPixel[2] = z + 1;
-
-    increment[0] = 1;
-    increment[1] = 1;
-    increment[2] = 1;
-
-    switch (bitPix) {
-    case BYTE_IMG:
-        datatype = PS_TYPE_U8;
-        fitsDatatype = TBYTE;
-        break;
-    case SBYTE_IMG:
-        datatype = PS_TYPE_S8;
-        fitsDatatype = TSBYTE;
-        break;
-    case USHORT_IMG:
-        datatype = PS_TYPE_U16;
-        fitsDatatype = TUSHORT;
-        break;
-    case SHORT_IMG:
-        datatype = PS_TYPE_S16;
-        fitsDatatype = TSHORT;
-        break;
-    case ULONG_IMG:
-        datatype = PS_TYPE_U32;
-        fitsDatatype = TUINT;
-        break;
-    case LONG_IMG:
-        datatype = PS_TYPE_S32;
-        fitsDatatype = TINT;
-        break;
-    case LONGLONG_IMG:
-        datatype = PS_TYPE_S64;
-        fitsDatatype = TLONGLONG;
-        break;
-    case FLOAT_IMG:
-        datatype = PS_TYPE_F32;
-        fitsDatatype = TFLOAT;
-        break;
-    case DOUBLE_IMG:
-        datatype = PS_TYPE_F64;
-        fitsDatatype = TDOUBLE;
-        break;
-    default:
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_FITS_TYPE_UNSUPPORTED,
-                bitPix);
-        psFree(output);
-        return NULL;
-    }
-
-    output = psImageRecycle(output,
-                            lastPixel[0]-firstPixel[0]+1,
-                            lastPixel[1]-firstPixel[1]+1,
-                            datatype);
-
-    if (output == NULL) {
-        psError(PS_ERR_UNKNOWN, false,
-                "Failed to allocate a properly sized image.");
-        return false;
-    }
-
-    // n.b., this assumes contiguous image buffer
-    if (fits_read_subset(fits->p_fd, fitsDatatype, firstPixel, lastPixel, increment,
-                         NULL, output->data.V[0], &anynull, &status) != 0) {
-        psFree(output);
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_READ_FAILED,
-                fitsErr);
-        return NULL;
-    }
-
-    return output;
-
-}
-
-bool psFitsWriteImage(const psFits* fits,
-                      const psMetadata* header,
-                      const psImage* input,
-                      int numZPlanes,
-                      char* extname)
-{
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (input == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_IMAGE_NULL);
-        return false;
-    }
-    int numCols = input->numCols;
-    int numRows = input->numRows;
-
-    int status = 0;
-
-    // determine the FITS-equivalent parameters
-    int bitPix;
-    double bZero;
-    int dataType;
-    if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) {
-        return false;
-    }
-
-    int naxis = 3;
-    long naxes[3];
-
-    naxes[0] = numCols;
-    naxes[1] = numRows;
-    naxes[2] = numZPlanes;
-
-    if (numZPlanes < 2) {
-        naxis = 2;
-    }
-
-    fits_create_img(fits->p_fd, bitPix, naxis, naxes, &status);
-
-    if (extname != NULL) {
-        fits_update_key_str(fits->p_fd, "EXTNAME", (char*)extname, NULL, &status);
-    }
-
-    if (bZero != 0) {        // set the bscale/bzero
-        fits_write_key_dbl(fits->p_fd, "BZERO", bZero, 12, "Pixel Value Offset", &status);
-        fits_write_key_dbl(fits->p_fd, "BSCALE", 1.0, 12, "Pixel Value Scale", &status);
-        fits_set_bscale(fits->p_fd, 1.0, bZero, &status);
-    }
-
-    // write the header, if any.
-    if (header != NULL) {
-        psFitsWriteHeader(header, fits);
-    }
-
-    if (input->parent == NULL) { // if no parent, assume that the image data is contiguous
-        fits_write_img(fits->p_fd,
-                       dataType,              // datatype
-                       1,                     // writing to the first z-plane
-                       numCols*numRows,       // number of elements to write, i.e., the whole image
-                       input->data.V[0],      // the data
-                       &status);
-    } else { // image data may not be contiguous; write one row at a time
-        int firstPixel = 1;
-        for (int row = 0; row < numRows; row++) {
-            fits_write_img(fits->p_fd,
-                           dataType,          // datatype
-                           firstPixel,
-                           numCols,           // number of elements to write, i.e., one row's worth
-                           input->data.V[row],// the raw row data
-                           &status);
-            firstPixel += numCols;  // move to next row
-        }
-    }
-
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_WRITE_FAILED,
-                fits->filename, fitsErr);
-        return false;
-    }
-
-    return true;
-
-}
-
-bool psFitsUpdateImage(const psFits* fits,
-                       const psImage* input,
-                       psRegion region,
-                       int z)
-{
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (input == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_IMAGE_NULL);
-        return false;
-    }
-
-    // check to see if we are positioned on an image HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != IMAGE_HDU) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE);
-        return NULL;
-    }
-
-    int numCols = input->numCols;
-    int numRows = input->numRows;
-
-    // determine the FITS-equivalent parameters
-    int bitPix;
-    double bZero;
-    int dataType;
-    if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) {
-        return false;
-    }
-
-    //check to see if the HDU has the same datatype
-    int fileBitpix;
-    int naxis;
-    long nAxes[3];
-    nAxes[2] = 1;
-    fits_get_img_param(fits->p_fd, 3, &fileBitpix, &naxis, nAxes, &status);
-
-    //check to see if the HDU has the same datatype
-    if (bitPix != fileBitpix) {
-        char* fitsTypeStr;
-        char* imageTypeStr;
-        PS_TYPE_NAME(fitsTypeStr,fileBitpix);
-        PS_TYPE_NAME(imageTypeStr,input->type.type);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_IMAGE_UPDATE_TYPE_MISMATCH,
-                fitsTypeStr, imageTypeStr);
-        return false;
-    }
-
-    //check if the HDU has the z-plane requested
-    if (z >= nAxes[2]) {
-        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
-                PS_ERRORTEXT_psFits_FITS_Z_SMALL,
-                nAxes[2],z);
-        return false;
-    }
-
-    // determine the region in the FITS file domain
-    long firstPixel[3];
-    long lastPixel[3];
-
-    firstPixel[0] = region.x0 + 1;
-    firstPixel[1] = region.y0 + 1;
-    firstPixel[2] = z + 1;
-
-    if (region.x1 > 0) {
-        lastPixel[0] = region.x1;
-    } else {
-        lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0
-    }
-    if (region.y1 > 0) {
-        lastPixel[1] = region.y1;
-    } else {
-        lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0
-    }
-    lastPixel[2] = z + 1;
-
-    if (firstPixel[0] < 1 || firstPixel[0] > nAxes[0] ||
-            firstPixel[1] < 1 || firstPixel[1] > nAxes[1] ||
-            lastPixel[0] < 1 || lastPixel[0] > nAxes[0] ||
-            lastPixel[1] < 1 || lastPixel[1] > nAxes[1]) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                "Specified region [%d:%d,%d:%d], is not valid given the %dx%d FITS image.",
-                region.y0,region.y1-1,region.x0,region.x1-1);
-        return false;
-
-    }
-
-    int dx = lastPixel[0] - firstPixel[0];
-    int dy = lastPixel[1] - firstPixel[1];
-    if (dx > numCols ||
-            dy > numRows) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                "The region [%d:%d,%d:%d], is not valid given the input %dx%d image.",
-                firstPixel[1]-1,lastPixel[1]-1,
-                firstPixel[0]-1,lastPixel[0]-1,
-                numCols, numRows);
-        return false;
-    }
-
-    psImage* subset;
-    if (dx != numCols || dy != numRows) {
-        // the input image needs to be subsetted
-        subset = psImageSubset((psImage*)input,0,0,dx+1,dy+1);
-    } else {
-        subset = psMemIncrRefCounter((psImage*)input);
-    }
-
-    fits_write_subset(fits->p_fd, dataType, firstPixel, lastPixel, subset->data.V[0], &status);
-
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_WRITE_FAILED,
-                fits->filename, fitsErr);
-        return false;
-    }
-
-    return true;
-}
-
-bool psFitsWriteHeader(const psMetadata* header,
-                       const psFits* fits)
-{
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (header == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_METADATA_NULL);
-        return false;
-    }
-
-    int status = 0;
-
-    //transverse the metadata list and add each key.
-
-    psListIterator* iter = psListIteratorAlloc(header->list,PS_LIST_HEAD,true);
-    psMetadataItem* item;
-    while ( (item=psListGetAndIncrement(iter)) != NULL ) {
-        switch (item->type) {
-        case PS_META_BOOL: {
-                int value = item->data.B;
-                fits_update_key(fits->p_fd,
-                                TLOGICAL,
-                                item->name,
-                                &value,
-                                item->comment,
-                                &status);
-                break;
-            }
-        case PS_META_S32:
-            fits_update_key(fits->p_fd,
-                            TINT,
-                            item->name,
-                            &item->data.S32,
-                            item->comment,
-                            &status);
-            break;
-        case PS_META_F32:
-            fits_update_key(fits->p_fd,
-                            TFLOAT,
-                            item->name,
-                            &item->data.F32,
-                            item->comment,
-                            &status);
-            break;
-        case PS_META_F64:
-            fits_update_key(fits->p_fd,
-                            TDOUBLE,
-                            item->name,
-                            &item->data.F64,
-                            item->comment,
-                            &status);
-            break;
-        case PS_META_STR:
-            fits_update_key(fits->p_fd,
-                            TSTRING,
-                            item->name,
-                            item->data.V,
-                            item->comment,
-                            &status);
-            break;
-        default:  // all other META types are ignored
-            break;
-        }
-
-        if ( status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            (void)fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psFits_WRITE_FAILED,
-                    fits->filename, fitsErr);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-psMetadata* psFitsReadTableRow(const psFits* fits,
-                               int row)
-{
-    long numRows;
-    int numCols;
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    // check to see if we even are positioned on a table HDU
-    int hdutype;
-    fits_get_hdu_type(fits->p_fd,&hdutype, &status);
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_TABLE_TYPE);
-        return NULL;
-    }
-
-    // get the size of the FITS table
-    fits_get_num_rows(fits->p_fd, &numRows, &status);
-    fits_get_num_cols(fits->p_fd, &numCols, &status);
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-
-    // the row parameter in the proper range?
-    if (row < 0 || row >= numRows) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                PS_ERRORTEXT_psFits_ROW_INVALID,
-                row,numRows);
-        return NULL;
-    }
-
-    psMetadata* data = psMetadataAlloc();
-
-    int typecode;
-    long repeat;
-    long width;
-    char name[60];
-    for (int col = 1; col <= numCols; col++) {
-        // get the column name
-        if (hdutype == BINARY_TBL) {
-            fits_get_bcolparms(fits->p_fd, col, name,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
-        } else {
-            fits_get_acolparms(fits->p_fd, col, name,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
-        }
-
-        // get the column type
-        fits_get_coltype(fits->p_fd, col, &typecode, &repeat, &width, &status);
-
-        if (status == 0) {
-
-            #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE) \
-        case FITSTYPE: { \
-                NATIVETYPE value = 0; \
-                int anynul = 0; \
-                fits_read_col(fits->p_fd, FITSTYPE, col,row+1, \
-                              1, 1, NULL, &value, &anynul, &status); \
-                psMetadataAdd(data,PS_LIST_TAIL, name, \
-                              PS_META_##TYPE, \
-                              "", (ps##TYPE)value); \
-                break; \
-            }
-
-            switch (typecode) {
-            case TBYTE:
-            case TSHORT:
-            case TLONGLONG:
-                READ_TABLE_ROW_CASE(TLONG, long, S32)
-                READ_TABLE_ROW_CASE(TFLOAT, float, F32)
-                READ_TABLE_ROW_CASE(TDOUBLE, double, F64)
-                READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL);
-            case TSTRING: {
-                    char* value;
-                    int anynul = 0;
-                    fits_read_col(fits->p_fd, TSTRING, col,row+1,
-                                  1, 1, NULL, &value, &anynul, &status);
-                    if (anynul == 0) {
-                        psMetadataAdd(data,PS_LIST_TAIL, name,
-                                      PS_META_STR,
-                                      "", value);
-                    }
-                    break;
-                }
-            default:
-                psTrace("psFits.psFitsReadTableRow", 2,
-                        "Column %d or row %d was of a non primitive type, %d",
-                        col, row, typecode);
-            }
-        }
-
-        if ( status != 0) {
-            char fitsErr[MAX_STRING_LENGTH];
-            (void)fits_get_errstatus(status, fitsErr);
-            psError(PS_ERR_IO, true,
-                    PS_ERRORTEXT_psFits_GET_TABLE_ELEMENT,
-                    col,row,fitsErr);
-            psFree(data);
-            return NULL;
-        }
-
-    }
-
-    return data;
-}
-
-psArray* psFitsReadTableColumn(const psFits* fits,
-                               const char* colname)
-{
-    int colnum = 0;
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    // check to see if we even are positioned on a table HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_TABLE_TYPE);
-        return NULL;
-    }
-
-    // find the column by name
-    if ( fits_get_colnum(fits->p_fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_FIND_COLUMN,
-                colname, fitsErr);
-        return NULL;
-    }
-
-    // get the number of rows
-    long numRows = 0;
-    fits_get_num_rows(fits->p_fd, &numRows, &status);
-
-    // get the column length.
-    int width;
-    if ( fits_get_col_display_width(fits->p_fd, colnum, &width, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_COLTYPE,
-                fitsErr);
-        return NULL;
-    }
-
-    // allocate the buffers
-    psArray* result = psArrayAlloc(numRows);
-    for (int row = 0; row < numRows; row++) {
-        result->data[row] = psAlloc((width+1)*sizeof(char));
-    }
-    result->n = numRows;
-
-    fits_read_col_str(fits->p_fd,
-                      colnum,
-                      1, // firstrow
-                      1, // firestelem
-                      numRows,
-                      "", // nulstr
-                      (char**)result->data,
-                      NULL,
-                      &status);
-
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_TABLE_READ_COL,
-                fitsErr);
-        return NULL;
-    }
-
-    return result;
-}
-
-psVector* psFitsReadTableColumnNum(const psFits* fits,
-                                   const char* colname)
-{
-    int status = 0;
-    int colnum = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    // check to see if we even are positioned on a table HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_TABLE_TYPE);
-        return NULL;
-    }
-
-    // find the column by name
-    if ( fits_get_colnum(fits->p_fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_FIND_COLUMN,
-                colname, fitsErr);
-        return NULL;
-    }
-
-    // get the number of rows
-    long numRows = 0;
-    fits_get_num_rows(fits->p_fd,
-                      &numRows,
-                      &status);
-
-    // get the column datatype.
-    int typecode;
-    long repeat;
-    long width;
-    if ( fits_get_eqcoltype(fits->p_fd, colnum, &typecode, &repeat, &width, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_COLTYPE,
-                fitsErr);
-        return NULL;
-    }
-
-    psVector* result = psVectorAlloc(numRows, convertFitsToPsType(typecode));
-
-    fits_read_col(fits->p_fd,
-                  typecode,
-                  colnum,
-                  1 /* firstrow */,
-                  1 /* firstelem */,
-                  numRows,
-                  NULL,
-                  (psPtr)(result->data.U8),
-                  NULL,
-                  &status);
-
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_TABLE_READ_COL,
-                fitsErr);
-        return NULL;
-    }
-
-    return result;
-}
-
-
-psArray* psFitsReadTable(const psFits* fits)
-{
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return NULL;
-    }
-
-    // check to see if we even are positioned on a table HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_TABLE_TYPE);
-        return NULL;
-    }
-
-    // get the size of the FITS table
-    long numRows = 0;
-    fits_get_num_rows(fits->p_fd, &numRows, &status);
-    if ( status != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED,
-                fitsErr);
-        return NULL;
-    }
-
-    psArray* table = psArrayAlloc(numRows);
-
-    for (int row = 0; row < numRows; row++) {
-        table->data[row] = psFitsReadTableRow(fits,row);
-    }
-
-    return table;
-}
-
-bool psFitsWriteTable(const psFits* fits,
-                      psMetadata* header,
-                      psArray* table,
-                      char* extname)
-{
-    int status = 0;
-    psMetadataItem* item;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (table == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_IMAGE_NULL);
-        return false;
-    }
-
-    int rows = table->n;
-    if (rows < 1) {
-        // no table data, what can I do?
-        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
-                PS_ERRORTEXT_psFits_TABLE_EMPTY);
-        return false;
-    }
-
-    // find all the columns needed
-    psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->size);
-    columns->n=0;
-
-    // find the unique items in the array of metadata 'rows'
-    for (int row=0; row < rows; row++) {
-        psMetadata* rowMeta = table->data[row];
-        if (rowMeta != NULL) {
-            psListIterator* iter = psListIteratorAlloc(rowMeta->list,
-                                   PS_LIST_HEAD,true);
-            while ( (item=psListGetAndIncrement(iter)) != NULL) {
-                if (PS_META_IS_PRIMITIVE(item->type)) {
-                    bool found = false;
-                    for (int n=0; n < columns->n && ! found; n++) {
-                        if (strcmp(item->name,
-                                   ((psMetadataItem*)(columns->data[n]))->name) == 0) {
-                            found = true;
-                        }
-                    }
-                    if (! found) {
-                        psArrayAdd(columns, columns->nalloc, item);
-                    }
-                }
-            }
-            psFree(iter);
-        }
-    }
-
-    if (columns->n == 0) { // no table columns found
-        // XXX: Error?
-        return false;
-    }
-
-    //create list of column names and types.
-    psArray* columnNames = psArrayAlloc(columns->n);
-    psArray* columnTypes = psArrayAlloc(columns->n);
-    for (int n=0; n < columns->n; n++) {
-        char* fitsType;
-        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
-        if ( ! convertMetadataTypeToBinaryTForm(((psMetadataItem*)columns->data[n])->type,
-                                                &fitsType)) {
-            // XXX: error message
-            return false;
-        }
-        columnTypes->data[n] = fitsType;
-    }
-
-    fits_create_tbl(fits->p_fd,
-                    BINARY_TBL,
-                    table->n, // number of rows in table
-                    columns->n, // number of columns in table
-                    (char**)columnNames->data, // names of the columns
-                    (char**)columnTypes->data, // format of the columns
-                    NULL, // physical unit of columns
-                    extname, // extension name
-                    &status);
-
-    psFree(columnNames);
-    psFree(columnTypes);
-
-    // fill in the table elements with data
-    for (int n = 0; n < columns->n; n++) {
-        int row;
-        item = columns->data[n];
-        if (PS_META_IS_PRIMITIVE(item->type)) {
-            psVector* col = NULL;
-            switch (item->type) {
-            case PS_META_S32:
-                col = psVectorAlloc(table->n, PS_TYPE_S32);
-                for (row = 0; row < table->n; row++) {
-                    col->data.S32[row] = psMetadataLookupS32(NULL,
-                                         table->data[row],
-                                         item->name);
-                }
-                fits_write_col_int(fits->p_fd,
-                                   n+1, // column number
-                                   1, // firstrow
-                                   1, // firstelem
-                                   table->n, // nelements
-                                   col->data.S32,
-                                   &status);
-                break;
-            case PS_META_F32:
-                col = psVectorAlloc(table->n, PS_TYPE_F32);
-                for (row = 0; row < table->n; row++) {
-                    col->data.F32[row] = psMetadataLookupF32(NULL,
-                                         table->data[row],
-                                         item->name);
-                }
-                fits_write_col_flt(fits->p_fd,
-                                   n+1, // column number
-                                   1, // firstrow
-                                   1, // firstelem
-                                   table->n, // nelements
-                                   col->data.F32,
-                                   &status);
-                break;
-            case PS_META_F64:
-                col = psVectorAlloc(table->n, PS_TYPE_F64);
-                for (row = 0; row < table->n; row++) {
-                    col->data.F64[row] = psMetadataLookupF64(NULL,
-                                         table->data[row],
-                                         item->name);
-                }
-                fits_write_col_dbl(fits->p_fd,
-                                   n+1, // column number
-                                   1, // firstrow
-                                   1, // firstelem
-                                   table->n, // nelements
-                                   col->data.F64,
-                                   &status);
-                break;
-            case PS_META_BOOL:
-                col = psVectorAlloc(table->n, PS_TYPE_BOOL);
-                for (row = 0; row < table->n; row++) {
-                    col->data.S8[row] = psMetadataLookupBool(NULL,
-                                        table->data[row],
-                                        item->name);
-                }
-                fits_write_col_log(fits->p_fd,
-                                   n+1, // column number
-                                   1, // firstrow
-                                   1, // firstelem
-                                   table->n, // nelements
-                                   col->data.S8,
-                                   &status);
-                break;
-            default:
-                // XXX: error message?
-                break;
-            }
-            psFree(col);
-        } else if (item->type == PS_META_STR) {
-            psArray* col = psArrayAlloc(table->n);
-            for (row = 0; row < table->n; row++) {
-                col->data[row] = item->data.V;
-            }
-            fits_write_col_str(fits->p_fd,
-                               n, // column number
-                               1, // firstrow
-                               1, // firstelem
-                               table->n, // nelements
-                               (char**)col->data,
-                               &status);
-            psFree(col);
-        }
-    }
-
-    psFree(columns);
-
-    return true;
-}
-
-bool psFitsUpdateTable(const psFits* fits,
-                       psMetadata* data,
-                       int row)
-{
-    int status = 0;
-
-    if (fits == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_NULL);
-        return false;
-    }
-
-    if (data == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psFits_IMAGE_NULL);
-        return false;
-    }
-
-    // check to see if we even are positioned on a table HDU
-    int hdutype;
-    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0) {
-        char fitsErr[MAX_STRING_LENGTH];
-        (void)fits_get_errstatus(status, fitsErr);
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
-                fitsErr);
-        return false;
-    }
-    if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) {
-        psError(PS_ERR_IO, true,
-                PS_ERRORTEXT_psFits_NOT_TABLE_TYPE);
-        return false;
-    }
-
-    psMetadataIterator* iter = psMetadataIteratorAlloc(data,PS_LIST_HEAD,NULL);
-
-    psMetadataItem* item;
-
-    while ( (item=psMetadataGetAndIncrement(iter)) != NULL) {
-        if (PS_META_IS_PRIMITIVE(item->type)) {
-            // operating on primitive data type, i.e., not a complex object
-            int colnum = 0;
-
-            if ( fits_get_colnum(fits->p_fd, CASESEN, item->name, &colnum, &status) == 0) {
-                // cooresponding column found in table
-                int dataType = 0;
-                convertPsTypeToFits(item->type, NULL, NULL, &dataType);
-
-                if (fits_write_col(fits->p_fd, dataType, colnum, row+1, 1, 1, &item->data,&status) != 0) {
-                    char fitsErr[MAX_STRING_LENGTH];
-                    (void)fits_get_errstatus(status, fitsErr);
-                    psError(PS_ERR_IO, true,
-                            PS_ERRORTEXT_psFits_WRITE_FAILED,
-                            fits->filename, fitsErr);
-                    psFree(iter);
-                    return false;
-                }
-            } else {
-                // the column was not found.
-                psWarning("No column with the name '%s' exists in the table.",
-                          item->name);
-            }
-        }
-    }
-
-    psFree(iter);
-
-    return true;
-}
Index: trunk/psLib/src/fileUtils/psFits.h
===================================================================
--- trunk/psLib/src/fileUtils/psFits.h	(revision 3690)
+++ 	(revision )
@@ -1,268 +1,0 @@
-/** @file  psFits.h
- *
- *  @brief Contains Fits I/O routines
- *
- *  @ingroup FileIO
- *
- *  @author Robert DeSonia, MHPCC
- *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-03-24 23:52:25 $
- *
- *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
- */
-
-#ifndef PS_FITS_H
-#define PS_FITS_H
-
-#include<fitsio.h>
-
-#include "psType.h"
-#include "psArray.h"
-#include "psVector.h"
-#include "psMetadata.h"
-#include "psHash.h"
-#include "psImage.h"
-
-/// @addtogroup FileIO
-/// @{
-
-typedef enum {
-    PS_FITS_TYPE_NONE = -1,
-    PS_FITS_TYPE_IMAGE = IMAGE_HDU,
-    PS_FITS_TYPE_BINARY_TABLE = BINARY_TBL,
-    PS_FITS_TYPE_ASCII_TABLE = ASCII_TBL,
-    PS_FITS_TYPE_ANY = ANY_HDU
-} psFitsType;
-
-/** FITS file object.
- *
- *  This object should be considered opaque to the user; no item in this
- *  struct should be accessed directly.
- *
- */
-typedef struct
-{
-    fitsfile* p_fd;                    ///< the CFITSIO fits files handle.
-    const char* filename;              ///< the filename of the fits file
-}
-psFits;
-
-/** Opens a FITS file and allocates the associated psFits object.
- *
- *  @return psFits*    new psFits object for the FITS files specified or
- *                     NULL if the open of the FITS file failed
- */
-psFits* psFitsAlloc(
-    const char* name                   ///< the FITS file name
-);
-
-/** Moves the FITS HDU to the specified extension name.
- *
- *  @return psFitsType    The HDU type, or PS_FITS_TYPE_NONE if move failed.
- */
-bool psFitsMoveExtName(
-    const psFits* fits,                ///< the psFits object to move
-    const char* extname                ///< the extension name
-);
-
-/** Moves the FITS HDU to the specified extension number
- *
- *  @return psFitsType    The HDU type, or PS_FITS_TYPE_NONE if move failed.
- */
-bool psFitsMoveExtNum(
-    const psFits* fits,                ///< the psFits object to move
-    int extnum,                        ///< the extension number to move to (zero is primary HDU)
-    bool relative                      ///< if true, extnum is a relative number to the current position
-);
-
-/** Get the current extension number, where 0 is the primary HDU.
- *
- *  @return int        Current HDU number of the psFits file or < 0 if an error
- *                     occurred.
- */
-int psFitsGetExtNum(
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Get the current extension name.
- *
- *  @return int        Current HDU name of the psFits file or NULL if an
- *                     error occurred.
- */
-char* psFitsGetExtName(
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Set the current extension's name
- *
- *  @return bool       TRUE if the extension was successfully set, otherwise FALSE.
- */
-bool psFitsSetExtName(
-    const psFits* fits,                ///< the psFits object
-    const char* name                   ///< the extension name
-);
-
-/** Get the total number of HDUs in the FITS file.
- *
- *  @return int        The total number of HDUs in the FITS file or < 0 if an
- *                     error occurred.
- */
-int psFitsGetSize(
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Get the extension type of the current HDU.
- *
- *  @return psFitsType The type of the current HDU.  If PS_FITS_TYPE_UNKNOWN,
- *                     the type could not be determined.
- */
-psFitsType psFitsGetExtType(
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Reads the header of the current HDU.
- *
- *  @return psMetadata*   the header data
- */
-psMetadata* psFitsReadHeader(
-    psMetadata* out,
-    ///< The psMetadata to add the header data.  If null, a new psMetadata is created.
-
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Reads the header of all HDUs.  The current HDU is not changed.
- *
- *  @return psHash*      the header data
- */
-psHash* psFitsReadHeaderSet(
-    psHash* out,
-    ///< The psHash to add the header data via psMetadata items.  If null, a
-    ///< new psHash is created.  The keys of the psHash are the extension names
-    ///< of the cooresponding HDUs.
-
-    const psFits* fits                       ///< the psFits object
-);
-
-/** Writes the values of the metadata to the current HDU header.
- *
- *  @return bool        if TRUE, the write was successful, otherwise FALSE.
- */
-bool psFitsWriteHeader(
-    const psMetadata* header,          ///< the psMetadata data in which to write
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Reads an image, given the desired region and z-plane.
- *
- *  @return psImage*     the read image or NULL if there was an error.
- */
-psImage* psFitsReadImage(
-    psImage* out,                      ///< a psImage to recycle.
-    const psFits* fits,                ///< the psFits object
-    psRegion region,                   ///< the region in the FITS image to read
-    int z                              ///< the z-plane in the FITS image cube to read
-);
-
-/** Writes an image, given the desired region and z-plane.
- *
- *  @return bool        TRUE is the write was successful, otherwise FALSE.
- */
-bool psFitsWriteImage(
-    const psFits* fits,                ///< the psFits object
-    const psMetadata* header,          ///< header items for the new HDU.  Can be NULL.
-    const psImage* input,              ///< the image to output
-    int depth,                         ///< the number of z-planes of the FITS image data cube
-    char* extname                      ///< extension name
-);
-
-/** Updates the FITS file image, given the desired region and z-plane.
- *
- *  @return bool        TRUE is the write was successful, otherwise FALSE.
- */
-bool psFitsUpdateImage(
-    const psFits* fits,                ///< the psFits object
-    const psImage* input,              ///< the image to output
-    psRegion region,                   ///< the region in the FITS image to write
-    int z                              ///< the z-planes of the FITS image data cube to write
-);
-
-/** Reads a table row.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return psMetadata*    The table row's data.  The keys are the column names.
- */
-psMetadata* psFitsReadTableRow(
-    const psFits* fits,                ///< the psFits object
-    int row                            ///< row number to read
-);
-
-/** Reads a table column.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return psArray*    Array of data items for the specified column or NULL
- *                      if an error occurred.
- */
-psArray* psFitsReadTableColumn(
-    const psFits* fits,                ///< the psFits object
-    const char* colname                ///< the column name
-);
-
-/** Reads a table column of numbers.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return psVector*    Vector of data for the specified column or NULL
- *                       if an error occurred.
- */
-psVector* psFitsReadTableColumnNum(
-    const psFits* fits,                ///< the psFits object
-    const char* colname                ///< the column name
-);
-
-
-/** Reads a whole FITS table.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return psArray*     Array of psMetadata items, which contains the output
- *                       data items of each row.
- *
- *  @see psFitsReadTableRow
- */
-psArray* psFitsReadTable(
-    const psFits* fits                 ///< the psFits object
-);
-
-/** Writes a whole FITS table.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return bool        TRUE if the write was successful, otherwise FALSE
- *
- *  @see psFitsReadTableRow
- */
-bool psFitsWriteTable(
-    const psFits* fits,                ///< the psFits object
-    psMetadata* header,                ///< header items for the new HDU.  Can be NULL.
-    psArray* table,
-    ///< Array of psMetadata items, which contains the output data items of each row.
-    char* extname                      ///< extension name
-);
-
-
-/** Updates a FITS table.  The current HDU type must be either
- *  PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.
- *
- *  @return bool        TRUE if the write was successful, otherwise FALSE
- *
- *  @see psFitsWriteTable
- */
-bool psFitsUpdateTable(
-    const psFits* fits,                ///< the psFits object
-    psMetadata* data,
-    ///< Array of psMetadata items, which contains the output data items of each row.
-    int row                            ///< the row number to update.
-);
-
-/// @}
-
-#endif
Index: trunk/psLib/src/fileUtils/psLookupTable.c
===================================================================
--- trunk/psLib/src/fileUtils/psLookupTable.c	(revision 3690)
+++ 	(revision )
@@ -1,959 +1,0 @@
-/** @file  psLookupTable.c
-*
-*  @brief This file defines the structure and functions for table lookups.
-*
-*  @ingroup dataIO
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-08 17:58:57 $
-*
-*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
-*/
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-//#ifdef DARWIN
-#undef __STRICT_ANSI__
-//#endif
-#include <stdlib.h>
-//#ifdef DARWIN
-#define __STRICT_ANSI__
-//#endif
-#include <math.h>
-#include <stdlib.h>
-
-#include "psMemory.h"
-#include "psString.h"
-#include "psError.h"
-#include "psLookupTable.h"
-#include "psFileUtilsErrors.h"
-#include "psConstants.h"
-
-/******************************************************************************/
-/*  DEFINE STATEMENTS                                                         */
-/******************************************************************************/
-
-/** Maximum size of a string */
-#define MAX_STRING_LENGTH 256
-
-/******************************************************************************/
-/*  TYPE DEFINITIONS                                                          */
-/******************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  GLOBAL VARIABLES                                                         */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FILE STATIC VARIABLES                                                    */
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
-/*****************************************************************************/
-
-static bool ignoreLine(char *inString);
-static char *cleanString(char *inString, int sLen);
-static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
-static psU8 parseU8(char *inString, psParseErrorType *status);
-static psS8 parseS8(char *inString, psParseErrorType *status);
-static psU16 parseU16(char *inString, psParseErrorType *status);
-static psS16 parseS16(char *inString, psParseErrorType *status);
-static psU32 parseU32(char *inString, psParseErrorType *status);
-static psS32 parseS32(char *inString, psParseErrorType *status);
-static psU64 parseU64(char *inString, psParseErrorType *status);
-static psS64 parseS64(char *inString, psParseErrorType *status);
-static psF32 parseF32(char *inString, psParseErrorType *status);
-static psF64 parseF64(char *inString, psParseErrorType *status);
-static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status);
-static void lookupTableFree(psLookupTable* table);
-
-/** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
- *  must be null terminated. */
-static bool 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. */
-static char *cleanString(char *inString, int 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;
-}
-
-
-/** 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. */
-static char* getToken(char **inString, char *delimiter, psParseErrorType *status)
-{
-    char *cleanToken = NULL;
-    int 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 = PS_PARSE_ERROR_GENERAL;
-    }
-
-    return cleanToken;
-}
-
-/** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
-static psU8 parseU8(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU8 value = 0.0;
-
-
-    value = (psU8)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
-static psS8 parseS8(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS8 value = 0.0;
-
-
-    value = (psS8)strtol(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
-static psU16 parseU16(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU16 value = 0.0;
-
-
-    value = (psU16)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
-static psS16 parseS16(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS16 value = 0.0;
-
-
-    value = (psS16)strtol(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
-static psU32 parseU32(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU32 value = 0.0;
-
-
-    value = (psU32)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS32. The input string must be cleaned and null terminated. */
-static psS32 parseS32(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS32 value = 0.0;
-
-
-    value = (psS32)strtol(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
-static psU64 parseU64(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU64 value = 0.0;
-
-
-    value = (psU64)strtoull(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
-static psS64 parseS64(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS64 value = 0.0;
-
-
-    value = (psS64)strtoll(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psF32. The input string must be cleaned and null terminated. */
-static psF32 parseF32(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psF32 value = 0.0;
-
-
-    value = (psF32)strtof(inString, &end);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psF64. The input string must be cleaned and null terminated. */
-static psF64 parseF64(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psF64 value = 0.0;
-
-
-    value = (psF64)strtod(inString, &end);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a double precision number. The input string must be cleaned and null
- * terminated. */
-static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status)
-{
-    psElemType type;
-
-
-    if(vec == NULL) {
-        *status = 1;
-        return;
-    }
-
-    type = vec->type.type;
-
-    switch(type) {
-    case PS_TYPE_U8:
-        vec->data.U8[index] = parseU8(strValue, status);
-        break;
-    case PS_TYPE_S8:
-        vec->data.S8[index] = parseS8(strValue, status);
-        break;
-    case PS_TYPE_U16:
-        vec->data.U16[index] = parseU16(strValue, status);
-        break;
-    case PS_TYPE_S16:
-        vec->data.S16[index] = parseS16(strValue, status);
-        break;
-    case PS_TYPE_U32:
-        vec->data.U32[index] = parseU32(strValue, status);
-        break;
-    case PS_TYPE_S32:
-        vec->data.S32[index] = parseS32(strValue, status);
-        break;
-    case PS_TYPE_U64:
-        vec->data.U64[index] = parseU64(strValue, status);
-        break;
-    case PS_TYPE_S64:
-        vec->data.S64[index] = parseS64(strValue, status);
-        break;
-    case PS_TYPE_F32:
-        vec->data.F32[index] = parseF32(strValue, status);
-        break;
-    case PS_TYPE_F64:
-        vec->data.F64[index] = parseF64(strValue, status);
-        break;
-    default:
-        *status = PS_PARSE_ERROR_TYPE;
-    }
-
-    return;
-}
-
-static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
-{
-    switch(status) {
-    case PS_PARSE_ERROR_VALUE:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
-        break;
-    case PS_PARSE_ERROR_TYPE:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
-        break;
-    case PS_PARSE_ERROR_GENERAL:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
-        break;
-    default:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
-    }
-
-    return PS_LOOKUP_SUCCESS;
-}
-
-static void lookupTableFree(psLookupTable* table)
-{
-    if (table == NULL) {
-        return;
-    }
-
-    psFree(table->values);
-    psFree(table->index);
-    psFree((char*)table->fileName);
-}
-
-/*****************************************************************************/
-/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
-/*****************************************************************************/
-
-psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
-{
-    psLookupTable *outTable = NULL;
-
-
-    // Can't read table if you don't know its name
-    PS_PTR_CHECK_NULL(fileName,NULL);
-
-    // Allocate lookup table
-    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
-
-    // Set deallocator
-    psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
-
-    // Allocate and set metadata item comment
-    outTable->fileName = psStringCopy(fileName);
-
-    // Number of table rows and columns. Automatically resized by table read.
-    outTable->numRows = 0;
-    outTable->numCols = 0;
-
-    // Valid ranges. Automatically set by table read if both zero.
-    outTable->validFrom = validFrom;
-    outTable->validTo = validTo;
-
-    // Vector of independent index values. Filled by table read.
-    outTable->index = NULL;
-
-    // Array of dependent table values corresponding to index values. Filled by table read.
-    outTable->values = NULL;
-
-    return outTable;
-}
-
-#define UPDATE_VALID_TO_FROM(TABLE)                                             \
-switch (TABLE->index->type.type) {                                              \
-case PS_TYPE_U8:                                                                \
-    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
-    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
-    break;                                                                      \
-case PS_TYPE_S8:                                                                \
-    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
-    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
-    break;                                                                      \
-case PS_TYPE_U16:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_S16:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_U32:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_S32:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_U64:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_S64:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_F32:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-case PS_TYPE_F64:                                                               \
-    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
-    break;                                                                      \
-default:                                                                        \
-    TABLE->validFrom = (psF64)0;                                                \
-    TABLE->validTo   = (psF64)0;                                                \
-    break;                                                                      \
-}
-
-#define COPY_VECTOR_VALUES(VEC_OUT,INDEX_OUT,VEC_IN,INDEX_IN)                              \
-switch(((psVector*)(VEC_IN))->type.type) {                                                 \
-case PS_TYPE_U8:                                                                           \
-    ((psVector*)VEC_OUT)->data.U8[INDEX_OUT] = ((psVector*)VEC_IN)->data.U8[INDEX_IN];     \
-    break;                                                                                 \
-case PS_TYPE_U16:                                                                          \
-    ((psVector*)VEC_OUT)->data.U16[INDEX_OUT] = ((psVector*)VEC_IN)->data.U16[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_U32:                                                                          \
-    ((psVector*)VEC_OUT)->data.U32[INDEX_OUT] = ((psVector*)VEC_IN)->data.U32[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_U64:                                                                          \
-    ((psVector*)VEC_OUT)->data.U64[INDEX_OUT] = ((psVector*)VEC_IN)->data.U64[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_S8:                                                                           \
-    ((psVector*)VEC_OUT)->data.S8[INDEX_OUT] = ((psVector*)VEC_IN)->data.S8[INDEX_IN];     \
-    break;                                                                                 \
-case PS_TYPE_S16:                                                                          \
-    ((psVector*)VEC_OUT)->data.S16[INDEX_OUT] = ((psVector*)VEC_IN)->data.S16[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_S32:                                                                          \
-    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_S64:                                                                          \
-    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_F32:                                                                          \
-    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
-    break;                                                                                 \
-case PS_TYPE_F64:                                                                          \
-    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
-    break;                                                                                 \
-default:                                                                                   \
-    break;                                                                                 \
-}
-
-
-psLookupTable* psLookupTableRead(psLookupTable *table)
-{
-    bool typeLine = true;
-    char *line = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    char *linePtr = NULL;
-    psParseErrorType status = PS_PARSE_SUCCESS;
-    psParseErrorType lineStatus = PS_PARSE_SUCCESS;
-    psU64 lineCount = 0;
-    psU64 numRows = 0;
-    psU64 numCols = 0;
-    psU64 failedLines = 0;
-    FILE *fp = NULL;
-    psElemType elemType;
-    psVector *indexVec = NULL;
-    psVector *valuesVec = NULL;
-    psArray *values = NULL;
-    psBool sortIndex = false;
-
-    // Check for NULL input table
-    PS_PTR_CHECK_NULL(table,NULL);
-
-    // Check for input table with NULL file name
-    PS_PTR_CHECK_NULL(table->fileName,NULL);
-
-    // Open table file specified by table->fileName
-    if((fp=fopen(table->fileName, "r")) == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
-                table->fileName);
-        return table;
-    }
-
-    // Initialize vector pointers
-    indexVec = table->index;
-    values = table->values = psArrayAlloc(10);
-    values->n = 0;
-
-    // Create reusable line for continuous read
-    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
-
-    // Loop through file to get numRows, numCols, and column data types
-    while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
-
-        // Initialize variables for new line
-        linePtr = line;
-        lineCount++;
-
-        // If line is not a comment or blank, then extract data
-        if(!ignoreLine(linePtr)) {
-
-            if(typeLine == true) {
-
-                // Determine column types from first line in data file after comments
-                while((strType=getToken(&linePtr," ",&status))) {
-                    numCols++;
-                    typeLine = false;
-                    if(!strncmp(strType, "psU8", 4)) {
-                        elemType = PS_TYPE_U8;
-                    } else if(!strncmp(strType, "psS8", 4)) {
-                        elemType = PS_TYPE_S8;
-                    } else if(!strncmp(strType, "psU16", 5)) {
-                        elemType = PS_TYPE_U16;
-                    } else if(!strncmp(strType, "psS16", 5)) {
-                        elemType = PS_TYPE_S16;
-                    } else if(!strncmp(strType, "psU32", 5)) {
-                        elemType = PS_TYPE_U32;
-                    } else if(!strncmp(strType, "psS32", 5)) {
-                        elemType = PS_TYPE_S32;
-                    } else if(!strncmp(strType, "psU64", 5)) {
-                        elemType = PS_TYPE_U64;
-                    } else if(!strncmp(strType, "psS64", 5)) {
-                        elemType = PS_TYPE_S64;
-                    } else if(!strncmp(strType, "psF32", 5)) {
-                        elemType = PS_TYPE_F32;
-                    } else if(!strncmp(strType, "psF64", 5)) {
-                        elemType = PS_TYPE_F64;
-                    } else {
-                        status = PS_PARSE_ERROR_TYPE;
-                    }
-
-                    // Realloc number of columns as you go
-                    psVector* vec = psVectorAlloc(0, elemType);
-                    if(numCols == 1) {
-                        indexVec = vec;
-                    } else {
-                        psArrayAdd(values,0,vec);
-                        psFree(vec);
-                    }
-
-                    if(status) {
-                        printError(lineCount, strValue, status);
-                        failedLines++;
-                        lineStatus = status;
-                        status = PS_PARSE_SUCCESS;
-                    }
-                    psFree(strType);
-                }
-            } else {
-                // Parse and add values to all columns
-                numRows++;
-                numCols = 0;
-                while((strValue=getToken(&linePtr," ",&status))) {
-                    numCols++;
-
-                    // Realloc number of rows as you go
-                    if(numCols == 1) {
-                        sortIndex = false;
-                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
-                        parseValue(indexVec, numRows-1, strValue, &status);
-                    } else {
-                        valuesVec = values->data[numCols-2];
-                        valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
-                        parseValue(valuesVec, numRows-1, strValue, &status);
-                    }
-
-                    if(status) {
-                        printError(lineCount, strValue, status);
-                        failedLines++;
-                        lineStatus = status;
-                        status = PS_PARSE_SUCCESS;
-                    }
-                    psFree(strValue);
-                } // end while
-            } // end else
-        } // if ignoreLine
-    } // end while
-
-    psFree(line);
-
-    // Set table for return
-    table->numRows = numRows;
-    table->numCols = numCols-1;
-    table->index = indexVec;
-    table->values = values;
-
-    // Set table values to indicate error detected during the read
-    if(lineStatus) {
-        table->numRows = 0;
-        table->numCols = 0;
-        table->validFrom = 0;
-        table->validTo = 0;
-        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID);
-    } else {
-        // Check if index vector needs to be sorted
-        psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32);
-        sortedIndex = psVectorSortIndex(sortedIndex,table->index);
-        for(psS32 i = 0; i < numRows; i++ ) {
-            if(sortedIndex->data.U32[i] != i) {
-                sortIndex = true;
-                break;
-            }
-        }
-        // Check if it is necessary to sort value vectors
-        if(sortIndex) {
-            // Allocate new index vector
-            psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type);
-            // Allocate new value vectors
-            psArray* newValueArray = psArrayAlloc(numCols-1);
-            for(psS32 j = 0; j < numCols-1; j++) {
-                psS32 type = ((psVector*)(table->values->data[j]))->type.type;
-                newValueArray->data[j] = psVectorAlloc(numRows,type);
-            }
-            for(psS32 i = 0; i < numRows; i++) {
-                // Populate new index vector
-                psU32 sortIndex = sortedIndex->data.U32[i];
-                COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex)
-                // For every column populate new value vectors
-                for(psS32 j=0; j < numCols-1; j++) {
-                    COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex)
-                }
-            }
-            // Free old index vector
-            psFree(table->index);
-            // Free old value vectors
-            psFree(table->values);
-            // Assign new vector value to table
-            table->index = newIndexVector;
-            // Assign new value vectors to table array
-            table->values = newValueArray;
-        }
-        psFree(sortedIndex);
-        // Update the validTo and validFrom
-        UPDATE_VALID_TO_FROM(table)
-    }
-
-    fclose(fp);
-
-    return table;
-}
-
-#define CONVERT_VALUE_TO_F64(VECTOR,INDEX,RESULT)     \
-switch(VECTOR->type.type) {                           \
-case PS_TYPE_U8:                                      \
-    RESULT = (psF64)VECTOR->data.U8[INDEX];           \
-    break;                                            \
-case PS_TYPE_U16:                                     \
-    RESULT = (psF64)VECTOR->data.U16[INDEX];          \
-    break;                                            \
-case PS_TYPE_U32:                                     \
-    RESULT = (psF64)VECTOR->data.U32[INDEX];          \
-    break;                                            \
-case PS_TYPE_U64:                                     \
-    RESULT = (psF64)VECTOR->data.U64[INDEX];          \
-    break;                                            \
-case PS_TYPE_S8:                                      \
-    RESULT = (psF64)VECTOR->data.S8[INDEX];           \
-    break;                                            \
-case PS_TYPE_S16:                                     \
-    RESULT = (psF64)VECTOR->data.S16[INDEX];          \
-    break;                                            \
-case PS_TYPE_S32:                                     \
-    RESULT = (psF64)VECTOR->data.S32[INDEX];          \
-    break;                                            \
-case PS_TYPE_S64:                                     \
-    RESULT = (psF64)VECTOR->data.S64[INDEX];          \
-    break;                                            \
-case PS_TYPE_F32:                                     \
-    RESULT = (psF64)VECTOR->data.F32[INDEX];          \
-    break;                                            \
-case PS_TYPE_F64:                                     \
-    RESULT = VECTOR->data.F64[INDEX];                 \
-    break;                                            \
-default:                                              \
-    RESULT = NAN;                                     \
-    break;                                            \
-}
-
-
-#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
-switch (TABLE->index->type.type) {                                                 \
-case PS_TYPE_U8:                                                                   \
-    if( (psU8)index < TABLE->index->data.U8[0] ) {                                 \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU8)index > TABLE->index->data.U8[numRows-1]) {                          \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U16:                                                                  \
-    if( (psU16)index < TABLE->index->data.U16[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU16)index > TABLE->index->data.U16[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U32:                                                                  \
-    if( (psU32)index < TABLE->index->data.U32[0]) {                                \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) {                      \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U64:                                                                  \
-    if( (psU64)index < TABLE->index->data.U64[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU64)index > TABLE->index->data.U64[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S8:                                                                   \
-    if( (psS8)index < TABLE->index->data.S8[0] ) {                                 \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS8)index > TABLE->index->data.S8[numRows-1] ) {                         \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S16:                                                                  \
-    if( (psS16)index < TABLE->index->data.S16[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS16)index > TABLE->index->data.S16[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S32:                                                                  \
-    if( (psS32)index < TABLE->index->data.S32[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S64:                                                                  \
-    if( (psS64)index < TABLE->index->data.S64[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_F32:                                                                  \
-    if( (psF32)index < TABLE->index->data.F32[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_F64:                                                                  \
-    if( index < TABLE->index->data.F64[0] ) {                                      \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( index > TABLE->index->data.F64[numRows-1] ) {                              \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-default:                                                                           \
-    *status = PS_LOOKUP_ERROR;                                                     \
-    return NAN;                                                                    \
-    break;                                                                         \
-}                                                                                  \
-if(*status == PS_LOOKUP_PAST_TOP) {                                                \
-    CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out)         \
-    return out;                                                                    \
-} else if (*status == PS_LOOKUP_PAST_BOTTOM) {                                     \
-    CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \
-    return out;                                                                    \
-}
-
-
-psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
-{
-    psU64 hiIdx = 0;
-    psU64 loIdx = 0;
-    psU64 numRows = 0;
-    psU64 numCols = 0;
-    psF64 out = 0.0;
-    psF64 denom = 0.0;
-    psF64 convertVal = 0.0;
-    psF64 tempVal = 0.0;
-    psVector *indexVec = NULL;
-    psVector *valuesVec = NULL;
-    psArray *values = NULL;
-
-    // Error checks
-    // Set status to error prior to check since if checks fails it will immediately return
-    PS_PTR_CHECK_NULL(status,NAN);
-    *status = PS_LOOKUP_ERROR;
-    PS_PTR_CHECK_NULL(table,NAN);
-    indexVec = table->index;
-    values = table->values;
-    numRows = table->numRows;
-    numCols = table->numCols;
-    PS_PTR_CHECK_NULL(indexVec,NAN);
-    PS_PTR_CHECK_NULL(values,NAN);
-    PS_INT_CHECK_EQUALS(numRows, 0,NAN);
-    PS_INT_CHECK_EQUALS(numCols, 0,NAN);
-    PS_INT_CHECK_RANGE(column, 0, (int)(numCols-1), NAN);
-
-    valuesVec = (psVector*)values->data[column];
-    PS_PTR_CHECK_NULL(indexVec,NAN);
-
-    // Set status to success since it passed all parameter checks
-    *status = PS_LOOKUP_SUCCESS;
-
-    // Verify the index is within the bounds of the table
-    CHECK_LOWER_UPPER_BOUND(table,index,column)
-
-    // Find location in table where specified index is between to entries
-    CONVERT_VALUE_TO_F64(indexVec, 0, convertVal)
-    while(index > convertVal ) {
-        hiIdx++;
-        if(hiIdx >= numRows) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
-            *status = PS_LOOKUP_ERROR;
-            return NAN;
-        }
-        CONVERT_VALUE_TO_F64(indexVec, hiIdx, convertVal)
-    }
-
-    // Check for negative low index and generate error
-    loIdx = hiIdx--;
-    if(loIdx < 0) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
-                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
-        *status = PS_LOOKUP_ERROR;
-        return NAN;
-    }
-
-    // Perform linear interpolation to calculate return value
-    CONVERT_VALUE_TO_F64(indexVec, hiIdx, denom)
-    CONVERT_VALUE_TO_F64(indexVec, loIdx, convertVal);
-    denom -= convertVal;
-    if(fabs(denom) < FLT_EPSILON) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
-        *status = PS_LOOKUP_ERROR;
-        return NAN;
-    } else {
-        CONVERT_VALUE_TO_F64(valuesVec,hiIdx,tempVal)
-        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
-        tempVal -= convertVal;
-        CONVERT_VALUE_TO_F64(indexVec,loIdx,convertVal)
-        out = tempVal*(index-convertVal)/denom;
-        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
-        out += convertVal;
-    }
-
-    return out;
-}
-
-psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
-{
-    psU64 i = 0;
-    psU64 numCols = 0;
-    psVector *outVector = NULL;
-    psLookupStatusType status = PS_LOOKUP_SUCCESS;
-
-    // Error checks
-    PS_PTR_CHECK_NULL(table,NULL);
-    PS_PTR_CHECK_NULL(stats,NULL);
-    numCols = table->numCols;
-    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
-
-    outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
-
-    // Fill vectors with results and status of results
-    for(i=0; i<numCols; i++) {
-        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
-        stats->data.U32[i] = status;
-    }
-
-    return outVector;
-}
-
Index: trunk/psLib/src/fileUtils/psLookupTable.h
===================================================================
--- trunk/psLib/src/fileUtils/psLookupTable.h	(revision 3690)
+++ 	(revision )
@@ -1,112 +1,0 @@
-/** @file  psLookupTable.h
-*
-*  @brief This file defines the structure and functions for table lookups.
-*
-*  @ingroup dataIO
-*
-*  @author Ross Harman, MHPCC
-*
-*  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-08 17:58:57 $
-*
-*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
-*/
-
-#ifndef PS_LOOKUPTABLE_H
-#define PS_LOOKUPTABLE_H
-
-#include "psType.h"
-#include "psVector.h"
-#include "psArray.h"
-
-
-/** Lookup table structure
- *
- *  Holds table data read from external data files.
- *
- */
-typedef struct
-{
-    const char *fileName;              ///< Name of file with table
-    psU64 numRows;                     ///< Number of table rows
-    psU64 numCols;                     ///< Number of table columns
-    psF64 validFrom;                   ///< Lower bound for rable read
-    psF64 validTo;                     ///< Upper bound for table read
-    psVector *index;                   ///< Vector of independent index values
-    psArray *values;                   ///< Array of dependent table values corresponding to index values
-}
-psLookupTable;
-
-
-/** Lookup table lookup status and error conditions
- *
- *  Success, failure, and status conditions for table lookups.
- */
-typedef enum {
-    PS_LOOKUP_SUCCESS             = 0x0000,        ///< Table lookup succeeded
-    PS_LOOKUP_PAST_TOP            = 0x0101,        ///< Lookup off top of table
-    PS_LOOKUP_PAST_BOTTOM         = 0x0102,        ///< Lookup off bottom of table
-    PS_LOOKUP_ERROR               = 0x0104         ///< Any other type of lookup error
-} psLookupStatusType;
-
-/** Lookup table parse status and error conditions
- *
- *  Success, failure, and status conditions for table parsing.
- */
-typedef enum {
-    PS_PARSE_SUCCESS              = 0x0000,        ///< Table lookup succeeded
-    PS_PARSE_ERROR_TYPE           = 0x0101,        ///< Error parsing type
-    PS_PARSE_ERROR_VALUE          = 0x0102,        ///< Error parsing numerical value
-    PS_PARSE_ERROR_GENERAL        = 0x0104         ///< Any other type of lookup error
-}psParseErrorType;
-
-/** Allocator for psLookupTable struct
- *
- *  Allocates a new psLookupTable struct.
- *
- *  @return psLookupTable*     New psLookupTable struct.
- */
-psLookupTable* psLookupTableAlloc(
-    const char *fileName,           ///< Name of file to read
-    psF64 validFrom,                ///< Lower bound for rable read
-    psF64 validTo                   ///< Upper bound for table read
-);
-
-/** Read lookup table
- *
- *  Reads a lookup table and fills corresponding psLookupTable struct.
- *
- *  @return psLookupTable*     New psLookupTable struct.
- */
-psLookupTable* psLookupTableRead(
-    psLookupTable *table            ///< Table to read
-);
-
-/** Lookup and interpolate value from table.
- *
- *  Interpolates value from table. Sets status bit for success or one of several possible failure
- *  conditions.
- *
- *  @return psLookupTable*     New psLookupTable struct
- */
-psF64 psLookupTableInterpolate(
-    psLookupTable *table,           ///< Table with data
-    psF64 index,                    ///< Value to be interpolated
-    psU64 column,                   ///< Column in table to be interpolated
-    psLookupStatusType *status      ///< Status of lookup
-);
-
-/** Lookup and interpolate all values from table.
- *
- *  Interpolates all values from table. Sets status bit for success or one of several possible failure
- *  conditions.
- *
- *  @return psLookupTable*     New psLookupTable struct
- */
-psVector* psLookupTableInterpolateAll(
-    psLookupTable *table,           ///< Table with data
-    psF64 index,                    ///< Value to be interpolated
-    psVector *stats                 ///< Vector of status for each lookup
-);
-
-#endif
