gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 0a1036f 025/125: Data structure with name, uni


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 0a1036f 025/125: Data structure with name, units, comments and status
Date: Sun, 23 Apr 2017 22:36:29 -0400 (EDT)

branch: master
commit 0a1036f2fbc5e8edcfd486d053254056b0eb043c
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Data structure with name, units, comments and status
    
    In preparation for reading and writing FITS tables (and also more
    customizable image keyword outputs), the data structure now has several new
    elements: `status', `name', `units', and `comment'. The last three are
    strings.
    
    With these new elements the old `gal_fits_key' structure was no longer
    necessary for the `gal_fits_read_keywords' function. It can now directly
    save its results to the root data structure instead of requiring a unique
    structure for itself. `gal_fits_read_keywords' is now also able to read the
    units and comments of a keyword, which can be very useful.
    
    If the `BUNIT' and `EXTNAME' keywords are present in a FITS file,
    `gal_fits_read_img_hdu' will also read them store them in the structure for
    use by the programs.
    
    With the addition of these keywords, and also starting work on string
    datasets, the `gal_data_free' function was also updated to free all the
    arrays pointed to by the array of strings. Also, to allow arrays of data
    structures, freeing the actual data structure is now optional with this
    function: a new argument is added to it and corrected in all the programs
    that use it so far.
    
    With the same line of reasoning as above (to allow working on arrays of
    data structures), the lower level parts of `gal_data_alloc' have moved to
    the new `gal_data_initialize' function which will assume an already
    allocated data structure and just initialize its values.
    
    The old `txtarray.[ch]' files have been deleted and replaced with a new
    `txt.[ch]' for input and output on text files (to be similar to `fits.h').
---
 bin/arithmetic/arithmetic.c        |   6 +-
 configure.ac                       |  11 +-
 lib/Makefile.am                    |   4 +-
 lib/checkset.c                     |  18 +-
 lib/data-arithmetic-binary.c       |  14 +-
 lib/data-arithmetic-onlyint.c      |  18 +-
 lib/data-arithmetic-other.c        |  39 ++--
 lib/data-copy.c                    |   2 +-
 lib/data.c                         | 165 +++++++++-----
 lib/fits.c                         | 222 ++++++++++++-------
 lib/gnuastro/data.h                |  43 ++--
 lib/gnuastro/fits.h                |  24 +-
 lib/gnuastro/{txtarray.h => txt.h} |  48 ++--
 lib/txt.c                          |  49 +++++
 lib/txtarray.c                     | 438 -------------------------------------
 15 files changed, 428 insertions(+), 673 deletions(-)

diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 8e4895a..d2d5404 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -349,7 +349,7 @@ reversepolish(struct imgarithparams *p)
   if(p->up.typeset && p->outtype!=p->operands->data->type)
     {
       d1=gal_data_copy_to_new_type(p->operands->data, p->outtype);
-      gal_data_free(p->operands->data);
+      gal_data_free(p->operands->data, 0);
     }
   else
     d1=p->operands->data;
@@ -364,7 +364,7 @@ reversepolish(struct imgarithparams *p)
          printed as an integer.  */
       d2=gal_data_copy_to_new_type(d1, GAL_DATA_TYPE_DOUBLE);
       printf("%g\n", *(double *)d2->array);
-      gal_data_free(d2);
+      gal_data_free(d2, 0);
     }
   else
     {
@@ -377,7 +377,7 @@ reversepolish(struct imgarithparams *p)
 
   /* Clean up, note that above, we copied the pointer to `refdata->wcs'
      into `d1', so it is freed when freeing d1. */
-  gal_data_free(d1);
+  gal_data_free(d1, 0);
   free(p->refdata.dsize);
 
   /* Clean up. Note that the tokens were taken from the command-line
diff --git a/configure.ac b/configure.ac
index d2a13c1..36cda35 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,7 +12,7 @@
 # Original author:
 #     Mohammad Akhlaghi <address@hidden>
 # Contributing author(s):
-# Copyright (C) 2015, Free Software Foundation, Inc.
+# Copyright (C) 2015 - 2016, Free Software Foundation, Inc.
 #
 # Gnuastro is free software: you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -274,10 +274,11 @@ AC_DEFINE_UNQUOTED([CONF_SHOWFMT], [" %-20s"],
 
 
 
-# Choose the types for arithmetic operations. The initial list of values
-# given here specify the default list of types. If they have a value of 1,
-# they will be used unless the user configures with
-# `--disable-bin-op-TYPENAME', or `--enable-bin-op-TYPENAME=no'.
+# The native types for binary arithmetic operations, see the manual for a
+# detailed discussion. The initial list of values given here specify the
+# default list of types. If they have a value of 1, they will be
+# compiled. unless the user configures with `--disable-bin-op-TYPENAME', or
+# `--enable-bin-op-TYPENAME=no'.
 binop_uchar=1
 binop_char=0
 binop_ushort=0
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0284569..3099c4b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -44,7 +44,7 @@ libgnuastro_la_SOURCES = array.c box.c checkset.c 
configfiles.c data.c  \
   data-arithmetic-binary.c data-arithmetic-onlyint.c                    \
   data-arithmetic-other.c data-copy.c fits.c git.c linkedlist.c mesh.c  \
   mode.c polygon.c qsort.c spatialconvolve.c statistics.c threads.c     \
-  timing.c txtarray.c wcs.c
+  timing.c txt.c wcs.c
 
 
 
@@ -59,7 +59,7 @@ pkginclude_HEADERS = gnuastro/config.h $(headersdir)/array.h  
          \
   $(headersdir)/git.h $(headersdir)/linkedlist.h $(headersdir)/mesh.h   \
   $(headersdir)/polygon.h $(headersdir)/qsort.h                         \
   $(headersdir)/spatialconvolve.h $(headersdir)/statistics.h            \
-  $(headersdir)/threads.h $(headersdir)/wcs.h $(headersdir)/txtarray.h
+  $(headersdir)/threads.h $(headersdir)/wcs.h $(headersdir)/txt.h
 
 
 
diff --git a/lib/checkset.c b/lib/checkset.c
index de075e8..a0ac9b1 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -601,13 +601,17 @@ gal_checkset_malloc_cat(char *inname, char *toappend)
 void
 gal_checkset_allocate_copy(char *arg, char **copy)
 {
-  /* Allocate the necessary space: */
-  errno=0;
-  *copy=malloc(strlen(arg)+1);
-  if(*copy==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes to copy %s",
-          strlen(arg)+1, arg);
-  strcpy(*copy, arg);
+  if(arg)
+    {
+      errno=0;
+      *copy=malloc(strlen(arg)+1);
+      if(*copy==NULL)
+        error(EXIT_FAILURE, errno, "%zu bytes to copy %s",
+              strlen(arg)+1, arg);
+      strcpy(*copy, arg);
+    }
+  else
+    *copy=NULL;
 }
 
 
diff --git a/lib/data-arithmetic-binary.c b/lib/data-arithmetic-binary.c
index d53c06a..1dee7da 100644
--- a/lib/data-arithmetic-binary.c
+++ b/lib/data-arithmetic-binary.c
@@ -441,7 +441,7 @@ data_arithmetic_binary(int operator, unsigned char flags, 
gal_data_t *lo,
                        l->size>1 ? l->ndim  : r->ndim,
                        l->size>1 ? l->dsize : r->dsize,
                        l->size>1 ? l->wcs   : r->wcs,
-                       0, minmapsize );
+                       0, minmapsize, NULL, NULL, NULL );
 
 
   /* Start setting the operator and operands. */
@@ -473,14 +473,14 @@ data_arithmetic_binary(int operator, unsigned char flags, 
gal_data_t *lo,
      they are different from the original pointers, they were allocated. */
   if(flags & GAL_DATA_ARITH_FREE)
     {
-      if     (o==l)       gal_data_free(r);
-      else if(o==r)       gal_data_free(l);
-      else              { gal_data_free(l); gal_data_free(r); }
+      if     (o==l)       gal_data_free(r, 0);
+      else if(o==r)       gal_data_free(l, 0);
+      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
     }
   else
     {
-      if(l!=lo)           gal_data_free(l);
-      if(r!=ro)           gal_data_free(r);
+      if(l!=lo)           gal_data_free(l, 0);
+      if(r!=ro)           gal_data_free(r, 0);
     }
 
   /* The type of the output dataset (`o->type') was chosen from `l' and `r'
@@ -492,7 +492,7 @@ data_arithmetic_binary(int operator, unsigned char flags, 
gal_data_t *lo,
   if( o->type != otype )
     {
       tmp_o=gal_data_copy_to_new_type(o, otype);
-      gal_data_free(o);
+      gal_data_free(o, 0);
       o=tmp_o;
     }
 
diff --git a/lib/data-arithmetic-onlyint.c b/lib/data-arithmetic-onlyint.c
index f1a5f43..1164fab 100644
--- a/lib/data-arithmetic-onlyint.c
+++ b/lib/data-arithmetic-onlyint.c
@@ -375,7 +375,7 @@ data_arithmetic_onlyint_binary(int operator, unsigned char 
flags,
                        l->size>1 ? l->ndim  : r->ndim,
                        l->size>1 ? l->dsize : r->dsize,
                        l->size>1 ? l->wcs   : r->wcs,
-                       0, minmapsize );
+                       0, minmapsize, NULL, NULL, NULL );
 
 
   /* Start setting the operator and operands. */
@@ -405,14 +405,14 @@ data_arithmetic_onlyint_binary(int operator, unsigned 
char flags,
      they are different from the original pointers, they were allocated. */
   if(flags & GAL_DATA_ARITH_FREE)
     {
-      if     (o==l)       gal_data_free(r);
-      else if(o==r)       gal_data_free(l);
-      else              { gal_data_free(l); gal_data_free(r); }
+      if     (o==l)       gal_data_free(r, 0);
+      else if(o==r)       gal_data_free(l, 0);
+      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
     }
   else
     {
-      if(l!=lo)           gal_data_free(l);
-      if(r!=ro)           gal_data_free(r);
+      if(l!=lo)           gal_data_free(l, 0);
+      if(r!=ro)           gal_data_free(r, 0);
     }
 
   /* The type of the output dataset (`o->type') was chosen from `l' and `r'
@@ -424,7 +424,7 @@ data_arithmetic_onlyint_binary(int operator, unsigned char 
flags,
   if( o->type != otype )
     {
       tmp_o=gal_data_copy_to_new_type(o, otype);
-      gal_data_free(o);
+      gal_data_free(o, 0);
       o=tmp_o;
     }
 
@@ -465,7 +465,7 @@ data_arithmetic_bitwise_not(unsigned char flags, gal_data_t 
*in)
     o = in;
   else
     o = gal_data_alloc(NULL, in->type, in->ndim, in->dsize, in->wcs,
-                       0, in->minmapsize);
+                       0, in->minmapsize, NULL, NULL, NULL);
 
   /* Start setting the types. */
   switch(in->type)
@@ -503,7 +503,7 @@ data_arithmetic_bitwise_not(unsigned char flags, gal_data_t 
*in)
      the pointers: if they are different from the original pointers, they
      were allocated. */
   if( (flags & GAL_DATA_ARITH_FREE) && o!=in)
-    gal_data_free(in);
+    gal_data_free(in, 0);
 
   /* Return */
   return o;
diff --git a/lib/data-arithmetic-other.c b/lib/data-arithmetic-other.c
index ed12c7d..bb26b2d 100644
--- a/lib/data-arithmetic-other.c
+++ b/lib/data-arithmetic-other.c
@@ -74,7 +74,7 @@ data_arithmetic_change_type(gal_data_t *data, int operator,
 
   /* Delete the input structure if the user asked for it. */
   if(flags & GAL_DATA_ARITH_FREE)
-    gal_data_free(data);
+    gal_data_free(data, 0);
 
   /* Return */
   return out;
@@ -115,7 +115,8 @@ data_arithmetic_not(gal_data_t *data, unsigned char flags)
 
   /* Allocate the output array. */
   out=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, data->ndim, data->dsize,
-                     data->wcs, 0, data->minmapsize);
+                     data->wcs, 0, data->minmapsize, data->name, data->unit,
+                     data->comment);
   o=out->array;
 
 
@@ -147,7 +148,7 @@ data_arithmetic_not(gal_data_t *data, unsigned char flags)
 
   /* Delete the input structure if the user asked for it. */
   if(flags & GAL_DATA_ARITH_FREE)
-    gal_data_free(data);
+    gal_data_free(data, 0);
 
   /* Return */
   return out;
@@ -183,7 +184,8 @@ data_arithmetic_abs(unsigned char flags, gal_data_t *in)
     out=in;
   else
     out = gal_data_alloc(NULL, in->type, in->ndim, in->dsize,
-                         in->wcs, 0, in->minmapsize);
+                         in->wcs, 0, in->minmapsize, in->name, in->unit,
+                         in->comment);
 
   /* Put the absolute value depending on the type. Note that the unsigned
      types are already positive, so if the input is not to be freed (the
@@ -230,7 +232,7 @@ data_arithmetic_abs(unsigned char flags, gal_data_t *in)
 
   /* Clean up and return */
   if( (flags & GAL_DATA_ARITH_FREE) && out!=in)
-    gal_data_free(in);
+    gal_data_free(in, 0);
   return out;
 }
 
@@ -461,11 +463,13 @@ data_arithmetic_unary_function(int operator, unsigned 
char flags,
 
     /* Operators with only one value as output. */
     case GAL_DATA_OPERATOR_MINVAL:
-      o = gal_data_alloc(NULL, in->type, 1, &dsize, NULL, 0, -1);
+      o = gal_data_alloc(NULL, in->type, 1, &dsize, NULL, 0, -1,
+                         NULL, NULL, NULL);
       gal_data_type_max(o->type, o->array);
       break;
     case GAL_DATA_OPERATOR_MAXVAL:
-      o = gal_data_alloc(NULL, in->type, 1, &dsize, NULL, 0, -1);
+      o = gal_data_alloc(NULL, in->type, 1, &dsize, NULL, 0, -1,
+                         NULL, NULL, NULL);
       gal_data_type_min(o->type, o->array);
       break;
 
@@ -475,7 +479,7 @@ data_arithmetic_unary_function(int operator, unsigned char 
flags,
         o = in;
       else
         o = gal_data_alloc(NULL, in->type, in->ndim, in->dsize, in->wcs,
-                           0, in->minmapsize);
+                           0, in->minmapsize, NULL, NULL, NULL);
     }
 
   /* Start setting the operator and operands. */
@@ -513,7 +517,7 @@ data_arithmetic_unary_function(int operator, unsigned char 
flags,
      the pointers: if they are different from the original pointers, they
      were allocated. */
   if( (flags & GAL_DATA_ARITH_FREE) && o!=in)
-    gal_data_free(in);
+    gal_data_free(in, 0);
 
   /* Return */
   return o;
@@ -658,7 +662,8 @@ data_arithmetic_binary_function_flt(int operator, unsigned 
char flags,
     o = gal_data_alloc(NULL, final_otype,
                        l->size>1 ? l->ndim  : r->ndim,
                        l->size>1 ? l->dsize : r->dsize,
-                       l->size>1 ? l->wcs : r->wcs, 0, minmapsize );
+                       l->size>1 ? l->wcs : r->wcs, 0, minmapsize,
+                       NULL, NULL, NULL);
 
 
   /* Start setting the operator and operands. */
@@ -681,9 +686,9 @@ data_arithmetic_binary_function_flt(int operator, unsigned 
char flags,
      were allocated. */
   if(flags & GAL_DATA_ARITH_FREE)
     {
-      if     (o==l)       gal_data_free(r);
-      else if(o==r)       gal_data_free(l);
-      else              { gal_data_free(l); gal_data_free(r); }
+      if     (o==l)       gal_data_free(r, 0);
+      else if(o==r)       gal_data_free(l, 0);
+      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
     }
 
   /* Return */
@@ -833,8 +838,8 @@ data_arithmetic_where(unsigned char flags, gal_data_t *out,
   /* Clean up if necessary. */
   if(flags & GAL_DATA_ARITH_FREE)
     {
-      gal_data_free(cond);
-      gal_data_free(iftrue);
+      gal_data_free(cond, 0);
+      gal_data_free(iftrue, 0);
     }
 }
 
@@ -1099,7 +1104,7 @@ data_arithmetic_multioperand(int operator, unsigned char 
flags,
     out = list;                 /* The top element in the list. */
   else
     out = gal_data_alloc(NULL, list->type, list->ndim, list->dsize,
-                         list->wcs, 0, list->minmapsize);
+                         list->wcs, 0, list->minmapsize, NULL, NULL, NULL);
 
 
   /* hasblank is used to see if a blank value should be checked or not. */
@@ -1155,7 +1160,7 @@ data_arithmetic_multioperand(int operator, unsigned char 
flags,
       while(tmp!=NULL)
         {
           ttmp=tmp->next;
-          if(tmp!=out) gal_data_free(tmp);
+          if(tmp!=out) gal_data_free(tmp, 0);
           tmp=ttmp;
         }
     }
diff --git a/lib/data-copy.c b/lib/data-copy.c
index 2142e96..82d0fbc 100644
--- a/lib/data-copy.c
+++ b/lib/data-copy.c
@@ -98,7 +98,7 @@ gal_data_copy_to_new_type(gal_data_t *in, int newtype)
 
   /* Allocate space for the output type */
   out=gal_data_alloc(NULL, newtype, in->ndim, in->dsize, in->wcs,
-                     0, in->minmapsize);
+                     0, in->minmapsize, in->name, in->unit, in->comment);
 
   /* Fill in the output array: */
   switch(newtype)
diff --git a/lib/data.c b/lib/data.c
index 0086537..7b6db63 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -361,48 +361,59 @@ gal_data_mmap(gal_data_t *data)
 
 
 
-/* Allocate a data structure based on the given parameters. If you want to
-   force the array into the hdd/ssd (mmap it), then set minmapsize=-1
-   (largest possible size_t value), in this way, no file will be larger. */
-gal_data_t *
-gal_data_alloc(void *array, int type, size_t ndim, long *dsize,
-               struct wcsprm *wcs, int clear, size_t minmapsize)
-{
-  size_t i;
-  gal_data_t in, *out;
+/* Initialize the data structure.
 
+   Some notes:
 
-  /* Allocate the space for the actual structure. */
-  errno=0;
-  out=malloc(sizeof *out);
-  if(out==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for gal_data_t in gal_data_alloc",
-          sizeof *out);
+   - The `status' value is the only element that cannot be set by this
+     function, it is initialized to zero.
+
+   - If no `array' is given, a blank array of the given size will be
+     allocated. If it is given the array pointer will be directly put here,
+     so do not free it independently any more. If you want a separate copy
+     of a dataset, you should use `gal_data_copy', not this function.
 
+   - Space for the `name', `unit', and `comment' strings within the data
+     structure are allocated here. So you can safely use literal strings,
+     or statically allocated ones, or simply the strings from other data
+     structures (and not have to worry about which one to free later).
+*/
+void
+gal_data_initialize(gal_data_t *data, void *array, int type,
+                    size_t ndim, long *dsize, struct wcsprm *wcs,
+                    int clear, size_t minmapsize, char *name,
+                    char *unit, char *comment)
+{
+  size_t i;
+  gal_data_t in;
 
-  /* Set the basic information we know so far. */
-  out->next=NULL;
-  out->ndim=ndim;
-  out->type=type;
-  out->minmapsize=minmapsize;
+  /* Do the simple copying  cases. */
+  data->status=0;
+  data->next=NULL;
+  data->ndim=ndim;
+  data->type=type;
+  data->minmapsize=minmapsize;
+  gal_checkset_allocate_copy(unit, &data->unit);
+  gal_checkset_allocate_copy(name, &data->name);
+  gal_checkset_allocate_copy(comment, &data->comment);
 
 
   /* Copy the WCS structure. Note that the `in' data structure was just
      defined to keep this pointer to call `gal_data_copy_wcs'. */
   in.wcs=wcs;
-  gal_data_copy_wcs(&in, out);
+  gal_data_copy_wcs(&in, data);
 
 
   /* Allocate space for the dsize array: */
   errno=0;
-  out->dsize=malloc(ndim*sizeof *out->dsize);
-  if(out==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for dsize in gal_data_alloc",
-          ndim*sizeof *out->dsize);
+  data->dsize=malloc(ndim*sizeof *data->dsize);
+  if(data->dsize==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for data->dsize in "
+          "`gal_data_alloc'", ndim*sizeof *data->dsize);
 
 
   /* Fill in the `dsize' array and in the meantime set `size': */
-  out->size=1;
+  data->size=1;
   for(i=0;i<ndim;++i)
     {
       /* Do a small sanity check. */
@@ -412,29 +423,57 @@ gal_data_alloc(void *array, int type, size_t ndim, long 
*dsize,
 
       /* Write this dimension's size, also correct the total number of
          elements. */
-      out->size *= ( out->dsize[i] = dsize[i] );
+      data->size *= ( data->dsize[i] = dsize[i] );
     }
 
 
   /* Allocate space for the array, clear it if necessary: */
   if(array)
-    out->array=array;
+    data->array=array;
   else
     {
-      if( gal_data_sizeof(type)*out->size  > minmapsize )
-        gal_data_mmap(out);
+      if( gal_data_sizeof(type)*data->size  > minmapsize )
+        gal_data_mmap(data);
       else
         {
           /* Allocate the space for the array. */
           if(clear)
-            out->array = gal_data_calloc_array(out->type, out->size);
+            data->array = gal_data_calloc_array(data->type, data->size);
           else
-            out->array = gal_data_malloc_array(out->type, out->size);
+            data->array = gal_data_malloc_array(data->type, data->size);
 
           /* Set the values. */
-          out->mmapname=NULL;
+          data->mmapname=NULL;
         }
     }
+}
+
+
+
+
+
+/* Allocate a data structure based on the given parameters. If you want to
+   force the array into the hdd/ssd (mmap it), then set minmapsize=-1
+   (largest possible size_t value), in this way, no file will be larger. */
+gal_data_t *
+gal_data_alloc(void *array, int type, size_t ndim, long *dsize,
+               struct wcsprm *wcs, int clear, size_t minmapsize,
+               char *title, char *unit, char *comment)
+{
+  gal_data_t *out;
+
+
+  /* Allocate the space for the actual structure. */
+  errno=0;
+  out=malloc(sizeof *out);
+  if(out==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for gal_data_t in gal_data_alloc",
+          sizeof *out);
+
+
+  /* Initialize the allocated array. */
+  gal_data_initialize(out, array, type, ndim, dsize, wcs, clear, minmapsize,
+                      title, unit, comment);
 
 
   /* Return the final structure. */
@@ -445,32 +484,54 @@ gal_data_alloc(void *array, int type, size_t ndim, long 
*dsize,
 
 
 
+/* Free the allocated contents of a data structure and possibly also the
+   data structure its self. When `only_contents' is zero, the actual data
+   structure will also be freed, see bellow.
+
+   The reason for the `only_contents' argument is that the data structure
+   might be allocated as an array (statically like `gal_data_t da[20]', or
+   dynamically like `gal_data_t *da; da=malloc(20*sizeof *da);'). In both
+   cases, a loop will be necessary to delete the allocated contents of each
+   element of the data structure array, but not the structure its
+   self. After that loop, if the array of data structures was statically
+   allocated, you don't have to do anything. If it was dynamically
+   allocated, we just have to run `free(da)'.*/
 void
-gal_data_free(gal_data_t *data)
+gal_data_free(gal_data_t *data, int only_contents)
 {
-  /* If there is a WCS structure, then free it. */
-  if(data->wcs)
-    wcsfree(data->wcs);
+  char **strarray=data->array;
+  char *str=strarray[0], *strf=str+data->size;
 
-  /* Free all the allocated space and finally the data structure itself. */
+  /* Free all the possible allocations. */
   free(data->dsize);
-
+  if(data->name) free(data->name);
+  if(data->unit) free(data->unit);
+  if(data->wcs) wcsfree(data->wcs);
+  if(data->comment) free(data->comment);
+
+  /* If the data type is string, then each element in the array is actually
+     a pointer to the array of characters, so free them before freeing the
+     actual array. */
+  if(data->type==GAL_DATA_TYPE_STRING)
+    do if(str) free(str); while(++str<strf);
+
+  /* Free the array. Note that if the array is mmap'd, then we need to
+     delete the file that kept it. */
   if(data->mmapname)
     {
       /* Delete the file keeping the array. */
       remove(data->mmapname);
 
-      /* If there is nothing else in the .gnuastro directory, then delete
-         the .gnuastro directory too. */
-
-      /* Free the file name space, and set it to NULL. */
+      /* Free the file name space. */
       free(data->mmapname);
-      data->mmapname=NULL;
     }
   else
     free(data->array);
 
-  free(data);
+
+  /* Finally, free the actual data structure. */
+  if(only_contents==0)
+    free(data);
 }
 
 
@@ -1158,7 +1219,8 @@ gal_data_flag_blank(gal_data_t *data)
 
   /* Allocate the output array. */
   out=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, data->ndim, data->dsize,
-                     data->wcs, 0, data->minmapsize);
+                     data->wcs, 0, data->minmapsize, data->name, data->unit,
+                     data->comment);
   o=out->array;
 
 
@@ -1402,7 +1464,7 @@ gal_data_to_same_type(gal_data_t *f,   gal_data_t *s,
     {
       *of=gal_data_copy_to_new_type(f, type);
       if(freeinputs)
-        gal_data_free(f);
+        gal_data_free(f, 0);
     }
   else
     *of=f;
@@ -1412,7 +1474,7 @@ gal_data_to_same_type(gal_data_t *f,   gal_data_t *s,
     {
       *os=gal_data_copy_to_new_type(s, type);
       if(freeinputs)
-        gal_data_free(s);
+        gal_data_free(s, 0);
     }
   else
     *os=s;
@@ -1530,7 +1592,8 @@ gal_data_string_to_number(char *string)
 
   /* Return the pointer to the data structure. */
   numarr=gal_data_alloc_number(type, ptr);
-  return gal_data_alloc(numarr, type, 1, dsize, NULL, 0, -1);
+  return gal_data_alloc(numarr, type, 1, dsize, NULL, 0, -1,
+                        NULL, NULL, NULL);
 }
 
 
@@ -1855,7 +1918,7 @@ data_arithmetic_convert_to_compiled_type(gal_data_t *in, 
unsigned char flags)
         {
           out=gal_data_copy_to_new_type(in, ntype);
           if(flags & GAL_DATA_ARITH_FREE)
-            { gal_data_free(in); in=NULL; }
+            { gal_data_free(in, 0); in=NULL; }
         }
       else
         {
@@ -1927,7 +1990,7 @@ gal_data_arithmetic(int operator, unsigned char flags, 
...)
     case GAL_DATA_OPERATOR_ISBLANK:
       d1 = va_arg(va, gal_data_t *);
       out = gal_data_flag_blank(d1);
-      if(flags & GAL_DATA_ARITH_FREE) gal_data_free(d1);
+      if(flags & GAL_DATA_ARITH_FREE) gal_data_free(d1, 0);
       break;
 
     case GAL_DATA_OPERATOR_WHERE:
diff --git a/lib/fits.c b/lib/fits.c
index b25e09b..bf733c0 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -623,39 +623,49 @@ gal_fits_read_hdu(char *filename, char *hdu, unsigned 
char img0_tab1,
 /**************************************************************/
 /**********            Header keywords             ************/
 /**************************************************************/
-/* Read keywords from a FITS file. The gal_fits_key pointer is an array of
-   gal_fits_key structures, which keep the basic information for each
-   keyword that is to be read and also stores the value in the appropriate
-   type.
+
+/* Each keyword name, value, comment, type is kept within a Gnuastro data
+   structure. The input should be an array of such data structures,
+   either statically allocated like:
+
+        gal_data_t keys[2];
+
+   or dynamically allocated like:
+
+        gal_data_t *keys;
+        keys=malloc(2*sizeof *keys);
+
+   Before calling this function, you just have to set the `title' and
+   `type' values of the data structure. The given title value will be
+   directly passed to CFITSIO to read the desired keyword.
+
+   CFITSIO will start searching for the keywords from the last place in the
+   header that it searched for a keyword. So it is much more efficient if
+   the order that you ask for keywords is based on the order they are
+   stored in the header.
 
    ABOUT THE STRING VALUES:
 
-   The space for a string value is statically allocated within the
+   The space for a string value is dynamically allocated within the
    `gal_fits_key' structure (to be `FLEN_VALUE' characters, `FLEN_VALUE' is
-   defined by CFITSIO). So if the value is necessary where `gal_fits_key'
-   is no longer available, then you have to allocate space dynamically and
-   copy the string there. */
+   defined by CFITSIO and is the largest possible number of characters).
+
+   This function will not abort if CFITSIO is unable to read the keyword
+   due to any reason. You can check the successful reading of the keyword
+   from the `status' value in each keyword's data structure. If its zero,
+   then the keyword was found and read as expected. Otherwise, this a
+   CFITSIO status, so you use its error reporting tools or
+   `gal_fits_io_error' for reporting the reason. If you have an alternative
+   to the keyword, or its not mandatory, and the keyword doesn't exist,
+   then the status value will be KEY_NO_EXIST (from CFITSIO).
+ */
 void
-gal_fits_read_keywords(char *filename, char *hdu, struct gal_fits_key *keys,
-                       size_t num)
+gal_fits_read_keywords_fptr(fitsfile *fptr, gal_data_t *keys, size_t num,
+                            int readcomment, int readunit)
 {
-  int status=0;
-  char *ffname;
-  size_t i, len;
-  fitsfile *fptr;
-  void *valueptr=NULL;
-
-  /* Add hdu to filename: */
-  errno=0;
-  len=strlen(filename)+strlen(hdu)+4;
-  ffname=malloc(len*sizeof *ffname);
-  if(ffname==NULL)
-    error(EXIT_FAILURE, errno, "%zu characters", len);
-  sprintf(ffname, "%s[%s#]", filename, hdu);
-
-  /* Open the FITS file: */
-  if( fits_open_file(&fptr, ffname, READONLY, &status) )
-    gal_fits_io_error(status, "reading this FITS file");
+  size_t i;
+  void *valueptr;
+  char **strarray;
 
   /* Get the desired keywords. */
   for(i=0;i<num;++i)
@@ -663,55 +673,99 @@ gal_fits_read_keywords(char *filename, char *hdu, struct 
gal_fits_key *keys,
       /* Initialize the status: */
       keys[i].status=0;
 
-      /* Set the value-pointer based on the required type. */
+      /* Allocate space for the desired type. */
+      keys[i].array=strarray=gal_data_malloc_array(keys[i].type, 1);
+
+      /* When the type is a string, `keys[i].array' will be keeping
+         pointers to a separately allocated piece of memory. So we have to
+         allocate that space here. If its not a string, then the
+         allocated space above is enough to keep the value.*/
       switch(keys[i].type)
         {
-        case GAL_DATA_TYPE_UCHAR:
-          valueptr=&keys[i].u;
-          break;
         case GAL_DATA_TYPE_STRING:
-          valueptr=keys[i].str;
-          break;
-        case GAL_DATA_TYPE_SHORT:
-          valueptr=&keys[i].s;
-          break;
-        case GAL_DATA_TYPE_LONG:
-          valueptr=&keys[i].l;
-          break;
-        case GAL_DATA_TYPE_LONGLONG:
-          valueptr=&keys[i].L;
-          break;
-        case GAL_DATA_TYPE_FLOAT:
-          valueptr=&keys[i].f;
-          break;
-        case GAL_DATA_TYPE_DOUBLE:
-          valueptr=&keys[i].d;
+          errno=0;
+          valueptr=strarray[0]=malloc(FLEN_VALUE * sizeof *strarray[0]);
+          if(strarray[0]==NULL)
+            error(EXIT_FAILURE, errno, "%zu bytes for strarray[0] in "
+                  "`gal_fits_read_keywords_fprt'",
+                  FLEN_VALUE * sizeof *strarray[0]);
           break;
+
         default:
-          error(EXIT_FAILURE, 0, "the value of keys[%zu].datatype (=%d) "
-                "is not recognized", i, keys[i].type);
+          valueptr=keys[i].array;
+        }
+
+      /* Allocate space for the keyword comment if necessary.*/
+      if(readcomment)
+        {
+          errno=0;
+          keys[i].comment=malloc(FLEN_COMMENT * sizeof *keys[i].comment);
+          if(keys[i].comment==NULL)
+            error(EXIT_FAILURE, errno, "%zu bytes for keys[i].comment in "
+                  "`gal_fits_read_keywords_fprt'",
+                  FLEN_COMMENT * sizeof *keys[i].comment);
         }
+      else
+        keys[i].comment=NULL;
+
+      /* Allocate space for the keyword unit if necessary. Note that since
+         there is no precise CFITSIO length for units, we will use the
+         `FLEN_COMMENT' length for units too (theoretically, the unit might
+         take the full remaining area in the keyword). Also note that the
+         unit is only optional, so it needs a separate CFITSIO function
+         call which is done here.*/
+      if(readunit)
+        {
+          errno=0;
+          keys[i].unit=malloc(FLEN_COMMENT * sizeof *keys[i].unit);
+          if(keys[i].unit==NULL)
+            error(EXIT_FAILURE, errno, "%zu bytes for keys[i].unit in "
+                  "`gal_fits_read_keywords_fprt'",
+                  FLEN_COMMENT * sizeof *keys[i].unit);
+          fits_read_key_unit(fptr, keys[i].name, keys[i].unit,
+                             &keys[i].status);
+        }
+      else
+        keys[i].unit=NULL;
 
-      /* Read the keyword and place its value in the poitner. */
+      /* Initialize the valueptr to NULL, then Read the keyword and place
+         its value in the poitner. */
+      valueptr=NULL;
       fits_read_key(fptr, gal_fits_type_to_datatype(keys[i].type),
-                    keys[i].keyname, valueptr, NULL, &keys[i].status);
-
-
-      /* In some cases, the caller might be fine with some kinds of errors,
-         so we will only report an error here is the situation is not
-         expected. For example, the caller might have alternatives for a
-         keyword if it doesn't exist, or the non-existence of a keyword
-         might itself be meaningful. So when the key doesn't exist, this
-         function will not abort, it will just keep the status.
-
-         The reason only non-existance is acceptable is this: if the
-         keyword does exist, but CFITSIO cannot read it due to some
-         technical difficulty, then the user probably wanted to give the
-         value. But is not aware of the technical problem.
-       */
-      if(keys[i].status!=0 && keys[i].status!=KEY_NO_EXIST)
-        gal_fits_io_error(keys[i].status, "reading the keyword");
+                    keys[i].name, valueptr, keys[i].comment,
+                    &keys[i].status);
     }
+}
+
+
+
+
+
+/* Same as `gal_fits_read_keywords_fptr', but accepts the filename and HDU
+   as input instead of an already opened CFITSIO `fitsfile' pointer. */
+void
+gal_fits_read_keywords(char *filename, char *hdu, gal_data_t *keys,
+                       size_t num, int readcomment, int readunit)
+{
+  size_t len;
+  int status=0;
+  char *ffname;
+  fitsfile *fptr;
+
+  /* Add hdu to filename: */
+  errno=0;
+  len=strlen(filename)+strlen(hdu)+4;
+  ffname=malloc(len*sizeof *ffname);
+  if(ffname==NULL)
+    error(EXIT_FAILURE, errno, "%zu characters", len);
+  sprintf(ffname, "%s[%s#]", filename, hdu);
+
+  /* Open the FITS file: */
+  if( fits_open_file(&fptr, ffname, READONLY, &status) )
+    gal_fits_io_error(status, "reading this FITS file");
+
+  /* Read the keywords. */
+  gal_fits_read_keywords_fptr(fptr, keys, num, readcomment, readunit);
 
   /* Close the FITS file. */
   fits_close_file(fptr, &status);
@@ -1207,7 +1261,8 @@ gal_fits_read_img_hdu(char *filename, char *hdu, char 
*maskname,
   fitsfile *fptr;
   int status=0, type;
   long *fpixel, *dsize;
-  gal_data_t *img, *mask;
+  char **str, *tmp, *name, *unit;
+  gal_data_t *img, *mask, keys[2];
 
 
   /* Check HDU for realistic conditions: */
@@ -1232,13 +1287,33 @@ gal_fits_read_img_hdu(char *filename, char *hdu, char 
*maskname,
   errno=0;
   fpixel=malloc(ndim*sizeof *fpixel);
   if(fpixel==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for fpixel in gal_fits_read_img_hdu",
-          ndim*sizeof *fpixel);
+    error(EXIT_FAILURE, errno, "%zu bytes for fpixel in "
+          "`gal_fits_read_img_hdu'", ndim*sizeof *fpixel);
   for(i=0;i<ndim;++i) fpixel[i]=1;
 
 
+  /* Read the possibly existing useful keywords. Note that the values are
+     in allocated strings in the keys[i] data structures. We don't want to
+     allocated them again, so we will just copy the pointers within the
+     `img' data structure and set the pointer in the keys[i] structure to
+     NULL. */
+  keys[0].name = "EXTNAME";
+  keys[1].name = "BUNIT";
+  keys[0].type=keys[1].type=GAL_DATA_TYPE_STRING;
+  gal_fits_read_keywords_fptr(fptr, keys, 2, 0, 0);
+  for(i=0;i<2;++i)
+    {
+      if(keys[0].status==0)
+        { str=keys[i].array; tmp=str[0]; str[0]=NULL; }
+      else tmp=NULL;
+      if(i==0) name=tmp; else unit=tmp;
+      gal_data_free(&keys[i], 1);
+    }
+
+
   /* Allocate the space for the array and for the blank values. */
-  img=gal_data_alloc(NULL, type, (long)ndim, dsize, NULL, 0, minmapsize);
+  img=gal_data_alloc(NULL, type, (long)ndim, dsize, NULL, 0, minmapsize,
+                     name, unit, NULL);
   blank=gal_data_alloc_blank(type);
   free(dsize);
 
@@ -1267,9 +1342,10 @@ gal_fits_read_img_hdu(char *filename, char *hdu, char 
*maskname,
       gal_data_apply_mask(img, mask);
 
       /* Free the mask space. */
-      gal_data_free(mask);
+      gal_data_free(mask, 0);
     }
 
+  /* Return the filled data structure */
   return img;
 }
 
@@ -1297,7 +1373,7 @@ gal_fits_read_to_type(char *inputname, char *inhdu, char 
*maskname,
   if(in->type!=type)
     {
       converted=gal_data_copy_to_new_type(in, type);
-      gal_data_free(in);
+      gal_data_free(in, 0);
       in=converted;
     }
 
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 579dd2a..fe3dea4 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -208,16 +208,27 @@ enum gal_data_operators
       type and this will make it easier to call CFITSIO functions.*/
 typedef struct gal_data_t
 {
-  void             *array;  /* Array keeping data elements.               */
-  int                type;  /* Type of data (from `gal_data_alltypes').   */
-  size_t             ndim;  /* Number of dimensions in the array.         */
-  long             *dsize;  /* Size of array along each dimension.        */
-  size_t             size;  /* Total number of data-elements.             */
-  char          *mmapname;  /* File name of the mmap.                     */
-  size_t       minmapsize;  /* Minimum number of bytes to mmap the array. */
-  int                nwcs;  /* for WCSLIB: no. coord. representations.    */
-  struct wcsprm      *wcs;  /* WCS information for this dataset.          */
-  struct gal_data_t *next;  /* To use it as a linked list if necessary.   */
+  /* Basic information on array of data. */
+  void             *array;  /* Array keeping data elements.                */
+  int                type;  /* Type of data (from `gal_data_alltypes').    */
+  size_t             ndim;  /* Number of dimensions in the array.          */
+  long             *dsize;  /* Size of array along each dimension.         */
+  size_t             size;  /* Total number of data-elements.              */
+  char          *mmapname;  /* File name of the mmap.                      */
+  size_t       minmapsize;  /* Minimum number of bytes to mmap the array.  */
+
+  /* WCS information. */
+  int                nwcs;  /* for WCSLIB: no. coord. representations.     */
+  struct wcsprm      *wcs;  /* WCS information for this dataset.           */
+
+  /* Content descriptions. */
+  int              status;  /* Any context-specific status value.          */
+  char              *name;  /* e.g., EXTNAME, or column, or keyword.       */
+  char              *unit;  /* Units of the data.                          */
+  char           *comment;  /* A more detailed description of the data.    */
+
+  /* As linked list. */
+  struct gal_data_t *next;  /* To use it as a linked list if necessary.    */
 } gal_data_t;
 
 
@@ -245,13 +256,19 @@ gal_data_calloc_array(int type, size_t size);
 void *
 gal_data_alloc_number(int type, void *number);
 
+void
+gal_data_initialize(gal_data_t *data, void *array, int type,
+                    size_t ndim, long *dsize, struct wcsprm *wcs,
+                    int clear, size_t minmapsize, char *name,
+                    char *unit, char *comment);
+
 gal_data_t *
 gal_data_alloc(void *array, int type, size_t ndim, long *dsize,
-               struct wcsprm *wcs, int clear, size_t minmapsize);
+               struct wcsprm *wcs, int clear, size_t minmapsize,
+               char *title, char *unit, char *comment);
 
 void
-gal_data_free(gal_data_t *data);
-
+gal_data_free(gal_data_t *data, int only_contents);
 
 
 
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index de2c7c0..b61c377 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -85,22 +85,6 @@ struct gal_fits_key_ll
 
 
 
-struct gal_fits_key
-{
-  int            status;        /* CFITSIO status.        */
-  char         *keyname;        /* Name of keyword.       */
-  int              type;        /* Type of keyword value. */
-  char  str[FLEN_VALUE];        /* String value.          */
-  unsigned char       u;        /* Byte value.            */
-  short               s;        /* Short integer value.   */
-  long                l;        /* Long integer value.    */
-  LONGLONG            L;        /* Long Long value.       */
-  float               f;        /* Float value.           */
-  double              d;        /* Double value.          */
-};
-
-
-
 /*************************************************************
  **************        Reporting errors:       ***************
  *************************************************************/
@@ -178,8 +162,12 @@ gal_fits_read_hdu(char *filename, char *hdu, unsigned char 
img0_tab1,
 /**********            Header keywords             ************/
 /**************************************************************/
 void
-gal_fits_read_keywords(char *filename, char *hdu, struct gal_fits_key *out,
-                       size_t num);
+gal_fits_read_keywords_fptr(fitsfile *fptr, gal_data_t *keys, size_t num,
+                            int readcomment, int readunit);
+
+void
+gal_fits_read_keywords(char *filename, char *hdu, gal_data_t *keys,
+                       size_t num, int readcomment, int readunit);
 
 void
 gal_fits_add_to_key_ll(struct gal_fits_key_ll **list, int datatype,
diff --git a/lib/gnuastro/txtarray.h b/lib/gnuastro/txt.h
similarity index 59%
rename from lib/gnuastro/txtarray.h
rename to lib/gnuastro/txt.h
index e889240..8b478f7 100644
--- a/lib/gnuastro/txtarray.h
+++ b/lib/gnuastro/txt.h
@@ -1,5 +1,5 @@
 /*********************************************************************
-txtarray -- Convert a text file table to a C array.
+data -- Structure and functions to represent/work with data
 This is part of GNU Astronomy Utilities (Gnuastro) package.
 
 Original author:
@@ -20,13 +20,25 @@ General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/
-#ifndef __GAL_TXTARRAY_H__
-#define __GAL_TXTARRAY_H__
+#ifndef __GAL_TXT_H__
+#define __GAL_TXT_H__
 
 /* Include other headers if necessary here. Note that other header files
    must be included before the C++ preparations below */
-#include <float.h>
 
+#include <gnuastro/data.h>
+
+/* When we are within Gnuastro's building process, `IN_GNUASTRO_BUILD' is
+   defined. In the build process, installation information (in particular
+   `GAL_CONFIG_ARITH_CHAR' and the rest of the types that we needed in the
+   arithmetic function) is kept in `config.h'. When building a user's
+   programs, this information is kept in `gnuastro/config.h'. Note that all
+   `.c' files must start with the inclusion of `config.h' and that
+   `gnuastro/config.h' is only created at installation time (not present
+   during the building of Gnuastro).*/
+#ifndef IN_GNUASTRO_BUILD
+#include <gnuastro/config.h>
+#endif
 
 /* C++ Preparations */
 #undef __BEGIN_C_DECLS
@@ -47,33 +59,11 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 
 
 
-/* Simple macros: */
-#define GAL_TXTARRAY_LOG "txtarray.log"
-
-
-
-
-
-/* Read a text table file into a double C array. Some tables might
-   have non-number elements, if so, they are put into
-   replacements. Replacements is an array of strings (pointers to
-   characters) similar to argv, since we need to allocate it inside
-   this function you have to give its pointer, hence three
-   dereferences. */
-void
-gal_txtarray_txt_to_array(char *filename, double **array,
-                          size_t *s0, size_t *s1);
-
-void
-gal_txtarray_printf_format(int numcols, char **fmt, int *int_cols,
-                           int *accu_cols, int *space, int *prec, char forg);
+gal_data_t *
+gal_txt_read_cols(char *filename, size_t *cols);
 
-void
-gal_txtarray_array_to_txt(double *array, size_t s0, size_t s1, char *comments,
-                          int *int_cols, int *accu_cols, int *space, int *prec,
-                          char forg, const char *filename);
 
 
 __END_C_DECLS    /* From C++ preparations */
 
-#endif           /* __GAL_TXTARRAY_H__ */
+#endif           /* __GAL_TXT_H__ */
diff --git a/lib/txt.c b/lib/txt.c
new file mode 100644
index 0000000..98147ee
--- /dev/null
+++ b/lib/txt.c
@@ -0,0 +1,49 @@
+/*********************************************************************
+txt -- Functions for I/O on text files.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2016, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+
+#include <gnuastro/data.h>
+
+
+/* Read the specified columns in a text file (named `filename' into an
+   array of data. The desired columns should be specified by the `cols'
+   array. Like a character string, the last element of this array is unique
+   and will mark its end. The unique value is `-1' (which is the largest
+   possible number in `size_t', since size_t is unsigned.
+
+   When the first element of the cols array is `-1', this function will
+   read all the columns from the text file and put the number of columns in
+   the space pointed to by `cols' (thus replacing the `-1' value). Note
+   that the number of rows is stored within each data element.*/
+gal_data_t *
+gal_txt_read_cols(char *filename, size_t *cols)
+{
+  gal_data_t *out=NULL;
+
+  return out;
+}
diff --git a/lib/txtarray.c b/lib/txtarray.c
deleted file mode 100644
index 0b5a54c..0000000
--- a/lib/txtarray.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*********************************************************************
-txtarray -- Convert a text file table to a C array.
-This is part of GNU Astronomy Utilities (Gnuastro) package.
-
-Original author:
-     Mohammad Akhlaghi <address@hidden>
-Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
-
-Gnuastro is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation, either version 3 of the License, or (at your
-option) any later version.
-
-Gnuastro is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
-**********************************************************************/
-#include <config.h>
-
-#include <math.h>
-#include <stdio.h>
-#include <errno.h>
-#include <error.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-#include <gnuastro/txtarray.h>
-
-
-
-
-/* Internal macros */
-#define GAL_TXTARRAY_FMT_LENGTH     50
-#define GAL_TXTARRAY_DELIMITERS    " ,\t\n"
-
-
-
-
-
-
-
-/**********************************************************************/
-/*****************       Read a text table        *********************/
-/**********************************************************************/
-static void
-txttablesize(char *filename, size_t *outs0, size_t *outs1)
-{
-  FILE *fp;
-  size_t len=200, s0, s1;
-  char *line, *firsttoken;
-
-  /* Initialize the sizes any way. */
-  s0=s1=0;
-
-  /* Allocate some space for `line` with `len` elements so it can
-     easily be freed later on. The value of `len` is arbitarary at
-     this point, during the run, getline will change it along with the
-     pointer to line. */
-  errno=0;
-  line=malloc(len*sizeof *line);
-  if(line==NULL)
-    error(EXIT_FAILURE, errno, "ui.c: %zu bytes in readdefaults",
-          len * sizeof *line);
-
-  /* Open the file: */
-  errno=0;
-  fp=fopen(filename, "r");
-  if(fp==NULL)
-    error(EXIT_FAILURE, errno, "%s", filename);
-
-  while( getline(&line, &len, fp) != -1 )
-    {
-      /* Read the first token: */
-      firsttoken=strtok(line, GAL_TXTARRAY_DELIMITERS);
-
-      /* If there are no non-delimters in the line (can happen if the
-         line is a blank line in the end of the file). */
-      if(firsttoken==NULL)
-        continue;
-
-      /* Check if it is a comment or new line character: */
-      if(firsttoken[0]=='#')
-        continue;
-
-      /* We are now in a data row: */
-      if(s0==0)  /* We are on the first row of data, find s1. */
-        {
-          s1=1;
-          while( strtok(NULL, GAL_TXTARRAY_DELIMITERS) != NULL )
-            ++s1;
-        }
-      ++s0;
-    }
-  free(line);
-
-  errno=0;
-  if(fclose(fp)==EOF)
-    error(EXIT_FAILURE, errno, "%s", filename);
-
-  if(s0==0 && s1==0)
-    error(EXIT_FAILURE, 0, "no table could be read in %s", filename);
-
-  *outs0=s0;
-  *outs1=s1;
-}
-
-
-
-
-
-static void
-savetolog(FILE **log, char *filename, size_t lineno, size_t s0,
-          size_t s1, char *token)
-{
-  if(*log)                        /* The file is already open. */
-    fprintf(*log, "%-10zu%-10zu%-10zu%s\n", lineno, s0, s1, token);
-  else                            /* Not yet created.          */
-    {
-      errno=0;
-      *log=fopen(GAL_TXTARRAY_LOG, "w");
-      if(*log==NULL)
-        error(EXIT_FAILURE, errno, "%s", filename);
-      fprintf(*log, "# Elements in %s which could not be read as a \n"
-              "# number. They are saved as nan in the array.\n"
-              "# The columns in the table below are:\n"
-              "# 0: Line number in file.\n"
-              "# 1: Row number in table (without commented or blank "
-              "lines).\n"
-              "# 2: Column number in table.\n"
-              "# 3: The string that could not be converted to a number.\n"
-              "# Note that counting starts from zero.\n",
-              filename);
-      fprintf(*log, "%-10zu%-10zu%-10zu%s\n", lineno-1, s0, s1, token);
-    }
-}
-
-
-
-
-
-/* Macro functions: */
-static double
-convertandsave(char *token, size_t lineno, char *filename, FILE *log,
-               size_t ts0, size_t ts1)
-{
-  double dout;
-  char *tailptr=NULL;
-
-  errno=0;
-  dout=strtod(token, &tailptr);
-  if(errno)
-    error_at_line(EXIT_FAILURE, errno, "%s", lineno, token, filename);
-  if(*tailptr!='\0')
-    {
-      savetolog(&log, filename, lineno, ts0, ts1, token);
-      dout=NAN;
-    }
-  return dout;
-}
-
-
-
-
-
-static void
-filltable(char *filename, double *array, size_t s0, size_t s1)
-{
-  FILE *fp, *log=NULL;
-  char *line=NULL, *token;
-  size_t len=200, lineno=0, ts0, ts1;
-
-  /* Open the file: */
-  errno=0;
-  fp=fopen(filename, "r");
-  if(fp==NULL)
-    error(EXIT_FAILURE, errno, "%s", filename);
-
-  /* Allocate some space for `line` with `len` elements so it can
-     easily be freed later on. The value of `len` is arbitarary at
-     this point, during the run, getline will change it along with the
-     pointer to line. */
-  errno=0;
-  line=malloc(len*sizeof *line);
-  if(line==NULL)
-    error(EXIT_FAILURE, errno, "ui.c: %zu bytes in readdefaults",
-          len * sizeof *line);
-
-  ts0=0;
-  while( getline(&line, &len, fp) != -1 )
-    {
-      ts1=0;
-      ++lineno;
-
-      /* Read the first token: */
-      token=strtok(line, GAL_TXTARRAY_DELIMITERS);
-
-      /* If there are no non-delimters in the line (can happen if the
-         line is a blank line in the end of the file). */
-      if(token==NULL)
-        continue;
-
-      /* Check if it is a comment or new line character: */
-      if(token[0]=='#')
-        continue;
-
-      /* Convert the first token and put it into the array: */
-      array[ts0*s1+ts1]=convertandsave(token, lineno, filename,
-                                       log, ts0, ts1);
-      ++ts1;
-
-      /* Read the rest of the tokens in this line. We had to do the first
-         token separately because of the nature of strtok: it can only be
-         used recursively after one proper call, see the GNU C Library
-         documentation for a complete explanation (this is a C standard
-         function, but GNU C Library has a wonderful manual). */
-      while( (token=strtok(NULL, GAL_TXTARRAY_DELIMITERS))!=NULL )
-        {
-          if(ts1>=s1)
-            error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                          "Too many columns on this line. The number of "
-                          "columns should be the same as the first row "
-                          "of the table.");
-          array[ts0*s1+ts1]=convertandsave(token, lineno, filename,
-                                           log, ts0, ts1);
-          ++ts1;
-        }
-      if(ts1<s1-1)                /* It should be s1-1. */
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      "Not enough columns on this line. The number of "
-                      "columns should be the same as the first row "
-                      "of the table.");
-      ++ts0;
-    }
-  free(line);
-
-  errno=0;
-  if(fclose(fp)==EOF)
-    error(EXIT_FAILURE, errno, "%s", filename);
-  if(log)
-    {
-      errno=0;
-      if(fclose(log)==EOF)
-        error(EXIT_FAILURE, errno, "%s", GAL_TXTARRAY_LOG);
-    }
-}
-
-
-
-
-
-void
-gal_txtarray_txt_to_array(char *filename, double **array,
-                          size_t *s0, size_t *s1)
-{
-  /* Find the size of the table and allocate space for it: */
-  errno=0;
-  txttablesize(filename, s0, s1);
-  if( (*array=malloc(*s0 * *s1 * sizeof **array)) == NULL)
-    error(EXIT_FAILURE, errno, "gal_txtarray_txt_to_array: space for "
-          "array with %zu elements", *s0 * *s1);
-
-  /* Fill in the table with the contents of the text file: */
-  filltable(filename, *array, *s0, *s1);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**********************************************************************/
-/*****************       Write a text table        ********************/
-/**********************************************************************/
-/* This function gets the formatting settings of the array as required
-   by writeasciitable and makes an array of formatting conditions that
-   is suitable for printing.  */
-void
-gal_txtarray_printf_format(int numcols, char **fmt, int *int_cols,
-                           int *accu_cols, int *space, int *prec, char forg)
-{
-  int i,j, found=0;
-
-  /* Initialize the format array: */
-  for (i=0;i<numcols;++i)
-    {
-      /* Allocate space for the format string of each column: */
-      errno=0;
-      fmt[i]=malloc(GAL_TXTARRAY_FMT_LENGTH * sizeof(char));
-      if(fmt[i]==NULL)
-        error(EXIT_FAILURE, errno, "txtarray, space for format "
-              "string %d, with %d elements", i, GAL_TXTARRAY_FMT_LENGTH);
-
-      /* See if this is an int column. */
-      found=0;
-      for(j=0;j<numcols;++j)
-        {
-          if (int_cols[j]<0) break;
-          if (i==int_cols[j])
-            {
-              sprintf(fmt[i], "%%-%d.0%c", space[0], forg);
-              found=1;break;
-            }
-        }
-      if (found==1) continue;
-
-      /* See if this is an extra precision column. */
-      found=0;
-      for(j=0;j<numcols;++j)
-        {
-          if (accu_cols[j]<0) break;
-          if (i==accu_cols[j])
-            {
-              sprintf(fmt[i], "%%-%d.%d%c", space[2], prec[1], forg);
-              found=1;break;
-            }
-        }
-      if (found==1) continue;
-
-      /* It is neither of the above, so it is a normal precision column. */
-      sprintf(fmt[i], "%%-%d.%d%c", space[1], prec[0], forg);
-    }
-}
-
-
-
-
-
-
-/* Write an array to a text file. It is assumed that we have three
-   types of input: Those who don't have any decimal point (ints),
-   those that need a small number of decimal accuracy and finally,
-   those that need to be very accurate. You specify the number of
-   digits after the decimal point along with all the other settings
-   with these input arrays:
-
-   int_cols: An array of integers showing the columns that are to be
-     printed with no decimal point. It should end with a negative
-     value to mark the end of the column numbers.
-
-   accu_cols: Similar to int_cols, but for columns which need extra
-     accuracy.
-
-   space: A three element array, which shows how much space should be
-     given to the three different types (the value immediately after %
-     in the format string).
-
-   prec: A two element array, showing the number of decimal points to
-     print the less and more accurate columns.
-
- */
-void
-gal_txtarray_array_to_txt(double *array, size_t s0, size_t s1,
-                          char *comments, int *int_cols, int *accu_cols,
-                          int *space, int *prec, char forg,
-                          const char *filename)
-{
-  int i,j;
-  FILE *fp;
-  char **fmt;
-
-  /* Do a small sanity check: */
-  for(i=0;int_cols[i]>0;++i)
-    if(int_cols[i]>=s1)
-      error(EXIT_FAILURE, 0, "gal_txtarray_array_to_txt: In int_cols[], "
-            "%d is larger than the number of columns: %zu", int_cols[i],
-            s1);
-  for(i=0;accu_cols[i]>0;++i)
-    if(accu_cols[i]>=s1)
-      error(EXIT_FAILURE, 0, "gal_txtarray_array_to_txt: In accu_cols[], "
-            "%d is larger than the number of columns: %zu", accu_cols[i],
-            s1);
-  for(i=0;i<3;++i)
-    if(space[i]<=0)
-      error(EXIT_FAILURE, 0, "gal_txtarray_array_to_txt: In space[], %d "
-            "is smaller or equal to zero", space[i]);
-  for(i=0;i<2;++i)
-    if(prec[i]<0)
-      error(EXIT_FAILURE, 0, "gal_txtarray_array_to_txt: In prec[], %d is "
-            "smaller than zero", space[i]);
-
-  /* Allocate the spaces: */
-  errno=0;
-  fmt=malloc(s1 * sizeof(char *));
-  if(fmt==NULL)
-    error(EXIT_FAILURE, errno, "txtarray, formatting of each "
-          "column with %zu elements", s1);
-
-  /* Prepare the formatting for each column */
-  gal_txtarray_printf_format(s1, fmt, int_cols, accu_cols,
-                             space, prec, forg);
-
-  /* Open the output file: */
-  errno=0;
-  fp=fopen(filename, "w");
-  if (fp==NULL)
-    error(EXIT_FAILURE, errno, "%s", filename);
-
-  /* Print the headers to file: */
-  if( comments[strlen(comments)-1]!='\n' )
-    fprintf(fp, "%s\n", comments);
-  else
-    fprintf(fp, "%s", comments);
-
-  /* Print the data to file: */
-  for(i=0;i<s0;++i)
-    {
-      for(j=0;j<s1;++j)
-        fprintf(fp, fmt[j], array[i*s1+j]);
-      fprintf(fp, "\n");
-    }
-
-  /* Close the file and free all pointers: */
-  errno=0;
-  if( fclose(fp) == EOF )
-    error(EXIT_FAILURE, errno, "%s", filename);
-  for(i=0;i<s1;++i) free(fmt[i]);
-  free(fmt);
-}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]