1 /*  This file, putcols.c, contains routines that write data elements to    */
2 /*  a FITS image or table, of type character string.                       */
3 
4 /*  The FITSIO software was written by William Pence at the High Energy    */
5 /*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
6 /*  Goddard Space Flight Center.                                           */
7 
8 #include <string.h>
9 #include <stdlib.h>
10 #include "fitsio2.h"
11 /*--------------------------------------------------------------------------*/
ffpcls(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char ** array,int * status)12 int ffpcls( fitsfile *fptr,  /* I - FITS file pointer                       */
13             int  colnum,     /* I - number of column to write (1 = 1st col) */
14             LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
15             LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
16             LONGLONG  nelem,     /* I - number of strings to write              */
17             char  **array,   /* I - array of pointers to strings            */
18             int  *status)    /* IO - error status                           */
19 /*
20   Write an array of string values to a column in the current FITS HDU.
21 */
22 {
23     int tcode, maxelem, hdutype, nchar;
24     long twidth, incre;
25     long ii, jj, ntodo;
26     LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
27     double scale, zero;
28     char tform[20], *blanks;
29     char message[FLEN_ERRMSG];
30     char snull[20];   /*  the FITS null value  */
31     tcolumn *colptr;
32 
33     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
34     char *buffer, *arrayptr;
35 
36     if (*status > 0)           /* inherit input status value if > 0 */
37         return(*status);
38 
39     /* reset position to the correct HDU if necessary */
40     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
41     {
42         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
43     }
44     else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
45     {
46         if ( ffrdef(fptr, status) > 0)               /* rescan header */
47             return(*status);
48     }
49 
50     /*---------------------------------------------------*/
51     /*  Check input and get parameters about the column: */
52     /*---------------------------------------------------*/
53     if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
54     {
55         snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
56                 colnum);
57         ffpmsg(message);
58         return(*status = BAD_COL_NUM);
59     }
60 
61     colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
62     colptr += (colnum - 1);     /* offset to correct column structure */
63     tcode = colptr->tdatatype;
64 
65     if (tcode == -TSTRING) /* variable length column in a binary table? */
66     {
67       /* only write a single string; ignore value of firstelem */
68       nchar = maxvalue(1,strlen(array[0])); /* will write at least 1 char */
69                                           /* even if input string is null */
70 
71       if (ffgcprll( fptr, colnum, firstrow, 1, nchar, 1, &scale, &zero,
72         tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
73         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
74         return(*status);
75 
76       /* simply move to write position, then write the string */
77       ffmbyt(fptr, startpos, IGNORE_EOF, status);
78       ffpbyt(fptr, nchar, array[0], status);
79 
80       if (*status > 0)  /* test for error during previous write operation */
81       {
82          snprintf(message,FLEN_ERRMSG,
83           "Error writing to variable length string column (ffpcls).");
84          ffpmsg(message);
85       }
86 
87       return(*status);
88     }
89     else if (tcode == TSTRING)
90     {
91       if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
92         tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
93         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
94         return(*status);
95 
96       /* if string length is greater than a FITS block (2880 char) then must */
97       /* only write 1 string at a time, to force writein by ffpbyt instead of */
98       /* ffpbytoff (ffpbytoff can't handle this case) */
99       if (twidth > IOBUFLEN) {
100         maxelem = 1;
101         incre = twidth;
102         repeat = 1;
103       }
104 
105       blanks = (char *) malloc(twidth); /* string for blank fill values */
106       if (!blanks)
107       {
108         ffpmsg("Could not allocate memory for string (ffpcls)");
109         return(*status = ARRAY_TOO_BIG);
110       }
111 
112       for (ii = 0; ii < twidth; ii++)
113           blanks[ii] = ' ';          /* fill string with blanks */
114 
115       remain = nelem;           /* remaining number of values to write  */
116     }
117     else
118       return(*status = NOT_ASCII_COL);
119 
120     /*-------------------------------------------------------*/
121     /*  Now write the strings to the FITS column.            */
122     /*-------------------------------------------------------*/
123 
124     next = 0;                 /* next element in array to be written  */
125     rownum = 0;               /* row number, relative to firstrow     */
126 
127     while (remain)
128     {
129       /* limit the number of pixels to process at one time to the number that
130          will fit in the buffer space or to the number of pixels that remain
131          in the current vector, which ever is smaller.
132       */
133       ntodo = (long) minvalue(remain, maxelem);
134       ntodo = (long) minvalue(ntodo, (repeat - elemnum));
135 
136       wrtptr = startpos + (rownum * rowlen) + (elemnum * incre);
137       ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */
138 
139       buffer = (char *) cbuff;
140 
141       /* copy the user's strings into the buffer */
142       for (ii = 0; ii < ntodo; ii++)
143       {
144          arrayptr = array[next];
145 
146          for (jj = 0; jj < twidth; jj++)  /*  copy the string, char by char */
147          {
148             if (*arrayptr)
149             {
150               *buffer = *arrayptr;
151               buffer++;
152               arrayptr++;
153             }
154             else
155               break;
156          }
157 
158          for (;jj < twidth; jj++)    /* fill field with blanks, if needed */
159          {
160            *buffer = ' ';
161            buffer++;
162          }
163 
164          next++;
165       }
166 
167       /* write the buffer full of strings to the FITS file */
168       if (incre == twidth)
169          ffpbyt(fptr, ntodo * twidth, cbuff, status);
170       else
171          ffpbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
172 
173       if (*status > 0)  /* test for error during previous write operation */
174       {
175          snprintf(message,FLEN_ERRMSG,
176           "Error writing elements %.0f thru %.0f of input data array (ffpcls).",
177              (double) (next+1), (double) (next+ntodo));
178          ffpmsg(message);
179 
180          if (blanks)
181            free(blanks);
182 
183          return(*status);
184       }
185 
186       /*--------------------------------------------*/
187       /*  increment the counters for the next loop  */
188       /*--------------------------------------------*/
189       remain -= ntodo;
190       if (remain)
191       {
192           elemnum += ntodo;
193           if (elemnum == repeat)  /* completed a row; start on next row */
194           {
195               elemnum = 0;
196               rownum++;
197           }
198        }
199     }  /*  End of main while Loop  */
200 
201     if (blanks)
202       free(blanks);
203 
204     return(*status);
205 }
206 /*--------------------------------------------------------------------------*/
ffpcns(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char ** array,char * nulvalue,int * status)207 int ffpcns( fitsfile *fptr,  /* I - FITS file pointer                       */
208             int  colnum,     /* I - number of column to write (1 = 1st col) */
209             LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
210             LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
211             LONGLONG  nelem,     /* I - number of values to write               */
212             char  **array,   /* I - array of values to write                */
213             char  *nulvalue, /* I - string representing a null value        */
214             int  *status)    /* IO - error status                           */
215 /*
216   Write an array of elements to the specified column of a table.  Any input
217   pixels flagged as null will be replaced by the appropriate
218   null value in the output FITS file.
219 */
220 {
221     long repeat, width;
222     LONGLONG ngood = 0, nbad = 0, ii;
223     LONGLONG first, fstelm, fstrow;
224 
225     if (*status > 0)
226         return(*status);
227 
228     /* reset position to the correct HDU if necessary */
229     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
230     {
231         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
232     }
233     else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
234     {
235         if ( ffrdef(fptr, status) > 0)               /* rescan header */
236             return(*status);
237     }
238 
239     /* get the vector repeat length of the column */
240     ffgtcl(fptr, colnum, NULL, &repeat, &width, status);
241 
242     if ((fptr->Fptr)->hdutype == BINARY_TBL)
243         repeat = repeat / width;    /* convert from chars to unit strings */
244 
245     /* absolute element number in the column */
246     first = (firstrow - 1) * repeat + firstelem;
247 
248     for (ii = 0; ii < nelem; ii++)
249     {
250       if (strcmp(nulvalue, array[ii]))  /* is this a good pixel? */
251       {
252          if (nbad)  /* write previous string of bad pixels */
253          {
254             fstelm = ii - nbad + first;  /* absolute element number */
255             fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
256             fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
257 
258             if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
259                 return(*status);
260             nbad=0;
261          }
262 
263          ngood = ngood +1;  /* the consecutive number of good pixels */
264       }
265       else
266       {
267          if (ngood)  /* write previous string of good pixels */
268          {
269             fstelm = ii - ngood + first;  /* absolute element number */
270             fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
271             fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
272 
273             if (ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
274                 status) > 0)
275                 return(*status);
276 
277             ngood=0;
278          }
279 
280          nbad = nbad +1;  /* the consecutive number of bad pixels */
281       }
282     }
283 
284     /* finished loop;  now just write the last set of pixels */
285 
286     if (ngood)  /* write last string of good pixels */
287     {
288       fstelm = ii - ngood + first;  /* absolute element number */
289       fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
290       fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
291 
292       ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
293     }
294     else if (nbad) /* write last string of bad pixels */
295     {
296       fstelm = ii - nbad + first;  /* absolute element number */
297       fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
298       fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
299 
300       ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
301     }
302 
303     return(*status);
304 }
305