Index: trunk/psLib/src/fits/psFitsTable.c
===================================================================
--- trunk/psLib/src/fits/psFitsTable.c	(revision 6484)
+++ trunk/psLib/src/fits/psFitsTable.c	(revision 6767)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-24 23:43:15 $
+ *  @version $Revision: 1.7 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-04 19:52:42 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -812,4 +812,226 @@
 }
 
+bool psFitsInsertTable(psFits* fits,
+                       const psMetadata* header,
+                       const psArray* table,
+                       bool after)
+{
+    int status = 0;
+
+    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->n);
+    columns->n=0;
+
+    // find the unique items in the array of metadata 'rows'
+    psMetadataItem* item;
+    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_DATA_IS_PRIMITIVE(item->type) ||
+                        item->type == PS_DATA_STRING ||
+                        item->type == PS_DATA_VECTOR) {
+                    bool found = false;
+                    psMetadataItem* fItem = NULL;
+                    int n;
+                    for (n=0; n < columns->n && ! found; n++) {
+                        fItem = (psMetadataItem*)(columns->data[n]);
+                        if (strcmp(item->name, fItem->name) == 0) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (! found) {
+                        psArrayAdd(columns, columns->nalloc, item);
+                    } else if (item->type == PS_DATA_STRING &&
+                               strlen(fItem->data.V) < strlen(item->data.V)) {
+                        // got to keep the longest string value as to know what size to create the table column
+                        psMemDecrRefCounter(fItem);
+                        columns->data[n] = psMemIncrRefCounter(item);
+                        columns->n++;
+
+                    } else if (item->type == PS_DATA_VECTOR &&
+                               ((psVector*)(fItem->data.V))->n < ((psVector*)(item->data.V))->n) {
+                        psMemDecrRefCounter(fItem);
+                        columns->data[n] = psMemIncrRefCounter(item);
+                        columns->n++;
+                    }
+                } else {
+                    // unsupported type -- treating as an error
+                    psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                            "Unsupported data type (%d) for Metadata Item '%s' in row %d.",
+                            item->type, item->name, row);
+                    psFree(iter);
+                    psFree(columns);
+                    return false;
+                }
+            }
+            psFree(iter);
+        }
+    }
+
+    if (columns->n == 0) { // no table columns found
+        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                "Did not find any column data to write to a table.");
+        psFree(columns);
+        return false;
+    }
+
+    //create list of column names and types.
+    columns->n--;
+    psArray* columnNames = psArrayAlloc(columns->n);
+    psArray* columnTypes = psArrayAlloc(columns->n);
+    for (int n=0; n < columns->n; n++) {
+        columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name);
+        columnNames->n++;
+        columnTypes->n++;
+        if ( ! getMetadataTForm((psMetadataItem*)columns->data[n],
+                                (char**)&(columnTypes->data[n]),1) ) {
+            psError(PS_ERR_UNKNOWN, true,
+                    "Failed to determine the FITS data type of '%s' (type=%d).",
+                    columnNames->data[n],
+                    ((psMetadataItem*)columns->data[n])->type);
+            psFree(columns);
+            psFree(columnNames);
+            psFree(columnTypes);
+            return false;
+        }
+    }
+
+    psString extname = NULL;
+    if (header != NULL) {
+        extname = psMetadataLookupStr(NULL, header, "EXTNAME");
+        if ( extname == NULL) {
+            extname = psMetadataLookupStr(NULL, header, "HDUNAME");
+        }
+    }
+
+    if (! after) {
+        if (psFitsGetExtNum(fits) == 0) {
+            // set status to signal fits_insert_img to insert a new primary HDU
+            status = PREPEND_PRIMARY;
+        } else {
+            // move back one to perform an insert after the previous HDU
+            psFitsMoveExtNum(fits, -1, true);
+        }
+    }
+
+    fits_insert_btbl(fits->fd,
+                     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
+                     0,
+                     &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_DATA_IS_PRIMITIVE(item->type) ) {
+            psVector* col = psVectorAlloc(table->n, item->type);
+            int dataSize = PSELEMTYPE_SIZEOF(item->type);
+            int dataType;
+            convertPsTypeToFits(item->type, NULL,NULL,&dataType);
+            for (row = 0; row < table->n; row++) {
+                psMetadataItem* dataItem = psMetadataLookup(
+                                               table->data[row],
+                                               item->name);
+                memcpy(&col->data.U8[row*dataSize],&dataItem->data,dataSize);
+            }
+            fits_write_col(fits->fd,
+                           dataType,
+                           n+1, // column number
+                           1, // firstrow
+                           1, // firstelem
+                           table->n, // nelements
+                           col->data.U8,
+                           &status);
+            psFree(col);
+        } else if (item->type == PS_DATA_STRING) {
+            psArray* colArray = psArrayAlloc(table->n);
+            for (row = 0; row < table->n; row++) {
+                colArray->data[row] = psStringCopy(psMetadataLookupStr(NULL,
+                                                   table->data[row],
+                                                   item->name));
+                colArray->n++;
+            }
+            fits_write_col_str(fits->fd,
+                               n+1,
+                               1,
+                               1,
+                               table->n,
+                               (char**)colArray->data,
+                               &status);
+            psFree(colArray);
+        } else if (item->type == PS_DATA_VECTOR) {
+            psVector* vec = (psVector*)(item->data.V);
+            psVector* col = psVectorAlloc(table->n*vec->n, vec->type.type);
+            int dataSize = PSELEMTYPE_SIZEOF(vec->type.type)*vec->n;
+            int dataType;
+            convertPsTypeToFits(vec->type.type, NULL,NULL,&dataType);
+            for (row = 0; row < table->n; row++) {
+                psMetadataItem* dataItem = psMetadataLookup(
+                                               table->data[row],
+                                               item->name);
+                memcpy(&col->data.U8[row*dataSize],
+                       ((psVector*)(dataItem->data.V))->data.U8,
+                       dataSize);
+            }
+            fits_write_col(fits->fd,
+                           dataType,
+                           n+1, // column number
+                           1, // firstrow
+                           1, // firstelem
+                           table->n*vec->n, // nelements
+                           col->data.U8,
+                           &status);
+            psFree(col);
+        }
+        if (status != 0) {
+            char fitsErr[MAX_STRING_LENGTH];
+            (void)fits_get_errstatus(status, fitsErr);
+            psError(PS_ERR_IO, true,
+                    PS_ERRORTEXT_psFits_WRITE_FAILED,
+                    fitsErr);
+            psFree(columns);
+            return false;
+        }
+
+    }
+
+    psFree(columns);
+
+    return true;
+}
+
 bool psFitsUpdateTable(psFits* fits,
                        const psMetadata* data,
