1 /* This file, getcols.c, contains routines that read data elements from */
2 /* a FITS image or table, with a character string datatype. */
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 <stdlib.h>
9 #include <string.h>
10 /* stddef.h is apparently needed to define size_t */
11 #include <stddef.h>
12 #include <ctype.h>
13 #include "fitsio2.h"
14 /*--------------------------------------------------------------------------*/
ffgcvs(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char * nulval,char ** array,int * anynul,int * status)15 int ffgcvs( fitsfile *fptr, /* I - FITS file pointer */
16 int colnum, /* I - number of column to read (1 = 1st col) */
17 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
18 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
19 LONGLONG nelem, /* I - number of strings to read */
20 char *nulval, /* I - string for null pixels */
21 char **array, /* O - array of values that are read */
22 int *anynul, /* O - set to 1 if any values are null; else 0 */
23 int *status) /* IO - error status */
24 /*
25 Read an array of string values from a column in the current FITS HDU.
26 Any undefined pixels will be set equal to the value of 'nulval' unless
27 nulval = null in which case no checks for undefined pixels will be made.
28 */
29 {
30 char cdummy[2];
31
32 ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, nulval,
33 array, cdummy, anynul, status);
34 return(*status);
35 }
36 /*--------------------------------------------------------------------------*/
ffgcfs(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,char ** array,char * nularray,int * anynul,int * status)37 int ffgcfs( fitsfile *fptr, /* I - FITS file pointer */
38 int colnum, /* I - number of column to read (1 = 1st col) */
39 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
40 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
41 LONGLONG nelem, /* I - number of strings to read */
42 char **array, /* O - array of values that are read */
43 char *nularray, /* O - array of flags = 1 if nultyp = 2 */
44 int *anynul, /* O - set to 1 if any values are null; else 0 */
45 int *status) /* IO - error status */
46 /*
47 Read an array of string values from a column in the current FITS HDU.
48 Nularray will be set = 1 if the corresponding array pixel is undefined,
49 otherwise nularray will = 0.
50 */
51 {
52 char dummy[2];
53
54 ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, dummy,
55 array, nularray, anynul, status);
56 return(*status);
57 }
58 /*--------------------------------------------------------------------------*/
ffgcls(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int nultyp,char * nulval,char ** array,char * nularray,int * anynul,int * status)59 int ffgcls( fitsfile *fptr, /* I - FITS file pointer */
60 int colnum, /* I - number of column to read (1 = 1st col) */
61 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
62 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
63 LONGLONG nelem, /* I - number of strings to read */
64 int nultyp, /* I - null value handling code: */
65 /* 1: set undefined pixels = nulval */
66 /* 2: set nularray=1 for undefined pixels */
67 char *nulval, /* I - value for null pixels if nultyp = 1 */
68 char **array, /* O - array of values that are read */
69 char *nularray, /* O - array of flags = 1 if nultyp = 2 */
70 int *anynul, /* O - set to 1 if any values are null; else 0 */
71 int *status) /* IO - error status */
72 /*
73 Read an array of string values from a column in the current FITS HDU.
74 Returns a formated string value, regardless of the datatype of the column
75 */
76 {
77 int tcode, hdutype, tstatus, scaled, intcol, dwidth, nulwidth, ll, dlen;
78 int equivtype;
79 long ii, jj;
80 tcolumn *colptr;
81 char message[FLEN_ERRMSG], *carray, keyname[FLEN_KEYWORD];
82 char cform[20], dispfmt[20], tmpstr[400], *flgarray, tmpnull[80];
83 unsigned char byteval;
84 float *earray;
85 double *darray, tscale = 1.0;
86 LONGLONG *llarray;
87 ULONGLONG *ullarray;
88
89 if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */
90 return(*status);
91
92 /* reset position to the correct HDU if necessary */
93 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
94 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
95
96 /* rescan header if data structure is undefined */
97 else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
98 if ( ffrdef(fptr, status) > 0)
99 return(*status);
100
101 if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
102 {
103 snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
104 colnum);
105 ffpmsg(message);
106 return(*status = BAD_COL_NUM);
107 }
108
109 /* get equivalent dataype of column (only needed for TLONGLONG columns) */
110 ffeqtyll(fptr, colnum, &equivtype, NULL, NULL, status);
111 if (equivtype < 0) equivtype = abs(equivtype);
112
113 colptr = (fptr->Fptr)->tableptr; /* point to first column */
114 colptr += (colnum - 1); /* offset to correct column structure */
115 tcode = abs(colptr->tdatatype);
116
117 if (tcode == TSTRING)
118 {
119 /* simply call the string column reading routine */
120 ffgcls2(fptr, colnum, firstrow, firstelem, nelem, nultyp, nulval,
121 array, nularray, anynul, status);
122 }
123 else if (tcode == TLOGICAL)
124 {
125 /* allocate memory for the array of logical values */
126 carray = (char *) malloc((size_t) nelem);
127
128 /* call the logical column reading routine */
129 ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, *nulval,
130 carray, nularray, anynul, status);
131
132 if (*status <= 0)
133 {
134 /* convert logical values to "T", "F", or "N" (Null) */
135 for (ii = 0; ii < nelem; ii++)
136 {
137 if (carray[ii] == 1)
138 strcpy(array[ii], "T");
139 else if (carray[ii] == 0)
140 strcpy(array[ii], "F");
141 else /* undefined values = 2 */
142 strcpy(array[ii],"N");
143 }
144 }
145
146 free(carray); /* free the memory */
147 }
148 else if (tcode == TCOMPLEX)
149 {
150 /* allocate memory for the array of double values */
151 earray = (float *) calloc((size_t) (nelem * 2), sizeof(float) );
152
153 ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
154 1, 1, FLOATNULLVALUE, earray, nularray, anynul, status);
155
156 if (*status <= 0)
157 {
158
159 /* determine the format for the output strings */
160
161 ffgcdw(fptr, colnum, &dwidth, status);
162 dwidth = (dwidth - 3) / 2;
163
164 /* use the TDISPn keyword if it exists */
165 ffkeyn("TDISP", colnum, keyname, status);
166 tstatus = 0;
167 cform[0] = '\0';
168
169 if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
170 {
171 /* convert the Fortran style format to a C style format */
172 ffcdsp(dispfmt, cform);
173 }
174
175 if (!cform[0])
176 strcpy(cform, "%14.6E");
177
178 /* write the formated string for each value: "(real,imag)" */
179 jj = 0;
180 for (ii = 0; ii < nelem; ii++)
181 {
182 strcpy(array[ii], "(");
183
184 /* test for null value */
185 if (earray[jj] == FLOATNULLVALUE)
186 {
187 strcpy(tmpstr, "NULL");
188 if (nultyp == 2)
189 nularray[ii] = 1;
190 }
191 else
192 snprintf(tmpstr, 400,cform, earray[jj]);
193
194 strncat(array[ii], tmpstr, dwidth);
195 strcat(array[ii], ",");
196 jj++;
197
198 /* test for null value */
199 if (earray[jj] == FLOATNULLVALUE)
200 {
201 strcpy(tmpstr, "NULL");
202 if (nultyp == 2)
203 nularray[ii] = 1;
204 }
205 else
206 snprintf(tmpstr, 400,cform, earray[jj]);
207
208 strncat(array[ii], tmpstr, dwidth);
209 strcat(array[ii], ")");
210 jj++;
211 }
212 }
213
214 free(earray); /* free the memory */
215 }
216 else if (tcode == TDBLCOMPLEX)
217 {
218 /* allocate memory for the array of double values */
219 darray = (double *) calloc((size_t) (nelem * 2), sizeof(double) );
220
221 ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
222 1, 1, DOUBLENULLVALUE, darray, nularray, anynul, status);
223
224 if (*status <= 0)
225 {
226 /* determine the format for the output strings */
227
228 ffgcdw(fptr, colnum, &dwidth, status);
229 dwidth = (dwidth - 3) / 2;
230
231 /* use the TDISPn keyword if it exists */
232 ffkeyn("TDISP", colnum, keyname, status);
233 tstatus = 0;
234 cform[0] = '\0';
235
236 if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
237 {
238 /* convert the Fortran style format to a C style format */
239 ffcdsp(dispfmt, cform);
240 }
241
242 if (!cform[0])
243 strcpy(cform, "%23.15E");
244
245 /* write the formated string for each value: "(real,imag)" */
246 jj = 0;
247 for (ii = 0; ii < nelem; ii++)
248 {
249 strcpy(array[ii], "(");
250
251 /* test for null value */
252 if (darray[jj] == DOUBLENULLVALUE)
253 {
254 strcpy(tmpstr, "NULL");
255 if (nultyp == 2)
256 nularray[ii] = 1;
257 }
258 else
259 snprintf(tmpstr, 400,cform, darray[jj]);
260
261 strncat(array[ii], tmpstr, dwidth);
262 strcat(array[ii], ",");
263 jj++;
264
265 /* test for null value */
266 if (darray[jj] == DOUBLENULLVALUE)
267 {
268 strcpy(tmpstr, "NULL");
269 if (nultyp == 2)
270 nularray[ii] = 1;
271 }
272 else
273 snprintf(tmpstr, 400,cform, darray[jj]);
274
275 strncat(array[ii], tmpstr, dwidth);
276 strcat(array[ii], ")");
277 jj++;
278 }
279 }
280
281 free(darray); /* free the memory */
282 }
283 else if (tcode == TLONGLONG && equivtype == TLONGLONG)
284 {
285 /* allocate memory for the array of LONGLONG values */
286 llarray = (LONGLONG *) calloc((size_t) nelem, sizeof(LONGLONG) );
287 flgarray = (char *) calloc((size_t) nelem, sizeof(char) );
288 dwidth = 20; /* max width of displayed long long integer value */
289
290 if (ffgcfjj(fptr, colnum, firstrow, firstelem, nelem,
291 llarray, flgarray, anynul, status) > 0)
292 {
293 free(flgarray);
294 free(llarray);
295 return(*status);
296 }
297
298 /* write the formated string for each value */
299 if (nulval) {
300 strncpy(tmpnull, nulval,79);
301 tmpnull[79]='\0'; /* In case len(nulval) >= 79 */
302 nulwidth = strlen(tmpnull);
303 } else {
304 strcpy(tmpnull, " ");
305 nulwidth = 1;
306 }
307
308 for (ii = 0; ii < nelem; ii++)
309 {
310 if ( flgarray[ii] )
311 {
312 *array[ii] = '\0';
313 if (dwidth < nulwidth)
314 strncat(array[ii], tmpnull, dwidth);
315 else
316 sprintf(array[ii],"%*s",dwidth,tmpnull);
317
318 if (nultyp == 2)
319 nularray[ii] = 1;
320 }
321 else
322 {
323
324 #if defined(_MSC_VER)
325 /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */
326 snprintf(tmpstr, 400,"%20I64d", llarray[ii]);
327 #elif (USE_LL_SUFFIX == 1)
328 snprintf(tmpstr, 400,"%20lld", llarray[ii]);
329 #else
330 snprintf(tmpstr, 400,"%20ld", llarray[ii]);
331 #endif
332 *array[ii] = '\0';
333 strncat(array[ii], tmpstr, 20);
334 }
335 }
336
337 free(flgarray);
338 free(llarray); /* free the memory */
339
340 }
341 else if (tcode == TLONGLONG && equivtype == TULONGLONG)
342 {
343 /* allocate memory for the array of ULONGLONG values */
344 ullarray = (ULONGLONG *) calloc((size_t) nelem, sizeof(ULONGLONG) );
345 flgarray = (char *) calloc((size_t) nelem, sizeof(char) );
346 dwidth = 20; /* max width of displayed unsigned long long integer value */
347
348 if (ffgcfujj(fptr, colnum, firstrow, firstelem, nelem,
349 ullarray, flgarray, anynul, status) > 0)
350 {
351 free(flgarray);
352 free(ullarray);
353 return(*status);
354 }
355
356 /* write the formated string for each value */
357 if (nulval) {
358 strncpy(tmpnull, nulval, 79);
359 tmpnull[79]='\0'; /* In case len(nulval) >= 79 */
360 nulwidth = strlen(tmpnull);
361 } else {
362 strcpy(tmpnull, " ");
363 nulwidth = 1;
364 }
365
366 for (ii = 0; ii < nelem; ii++)
367 {
368 if ( flgarray[ii] )
369 {
370 *array[ii] = '\0';
371 if (dwidth < nulwidth)
372 strncat(array[ii], tmpnull, dwidth);
373 else
374 sprintf(array[ii],"%*s",dwidth,tmpnull);
375
376 if (nultyp == 2)
377 nularray[ii] = 1;
378 }
379 else
380 {
381
382 #if defined(_MSC_VER)
383 /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */
384 snprintf(tmpstr, 400, "%20I64u", ullarray[ii]);
385 #elif (USE_LL_SUFFIX == 1)
386 snprintf(tmpstr, 400, "%20llu", ullarray[ii]);
387 #else
388 snprintf(tmpstr, 400, "%20lu", ullarray[ii]);
389 #endif
390 *array[ii] = '\0';
391 strncat(array[ii], tmpstr, 20);
392 }
393 }
394
395 free(flgarray);
396 free(ullarray); /* free the memory */
397
398 }
399 else
400 {
401 /* allocate memory for the array of double values */
402 darray = (double *) calloc((size_t) nelem, sizeof(double) );
403
404 /* read all other numeric type columns as doubles */
405 if (ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, nultyp,
406 DOUBLENULLVALUE, darray, nularray, anynul, status) > 0)
407 {
408 free(darray);
409 return(*status);
410 }
411
412 /* determine the format for the output strings */
413
414 ffgcdw(fptr, colnum, &dwidth, status);
415
416 /* check if column is scaled */
417 ffkeyn("TSCAL", colnum, keyname, status);
418 tstatus = 0;
419 scaled = 0;
420 if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
421 {
422 if (tscale != 1.0)
423 scaled = 1; /* yes, this is a scaled column */
424 }
425
426 intcol = 0;
427 if (tcode <= TLONG && !scaled)
428 intcol = 1; /* this is an unscaled integer column */
429
430 /* use the TDISPn keyword if it exists */
431 ffkeyn("TDISP", colnum, keyname, status);
432 tstatus = 0;
433 cform[0] = '\0';
434
435 if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
436 {
437 /* convert the Fortran style TDISPn to a C style format */
438 ffcdsp(dispfmt, cform);
439 }
440
441 if (!cform[0])
442 {
443 /* no TDISPn keyword; use TFORMn instead */
444
445 ffkeyn("TFORM", colnum, keyname, status);
446 ffgkys(fptr, keyname, dispfmt, NULL, status);
447
448 if (scaled && tcode <= TSHORT)
449 {
450 /* scaled short integer column == float */
451 strcpy(cform, "%#14.6G");
452 }
453 else if (scaled && tcode == TLONG)
454 {
455 /* scaled long integer column == double */
456 strcpy(cform, "%#23.15G");
457 }
458 else if (scaled && tcode == TLONGLONG)
459 {
460 /* scaled long long integer column == double */
461 strcpy(cform, "%#23.15G");
462 }
463 else
464 {
465 ffghdt(fptr, &hdutype, status);
466 if (hdutype == ASCII_TBL)
467 {
468 /* convert the Fortran style TFORMn to a C style format */
469 ffcdsp(dispfmt, cform);
470 }
471 else
472 {
473 /* this is a binary table, need to convert the format */
474 if (tcode == TBIT) { /* 'X' */
475 strcpy(cform, "%4d");
476 } else if (tcode == TBYTE) { /* 'B' */
477 strcpy(cform, "%4d");
478 } else if (tcode == TSHORT) { /* 'I' */
479 strcpy(cform, "%6d");
480 } else if (tcode == TLONG) { /* 'J' */
481 strcpy(cform, "%11.0f");
482 intcol = 0; /* needed to support unsigned int */
483 } else if (tcode == TFLOAT) { /* 'E' */
484 strcpy(cform, "%#14.6G");
485 } else if (tcode == TDOUBLE) { /* 'D' */
486 strcpy(cform, "%#23.15G");
487 }
488 }
489 }
490 }
491
492 if (nulval) {
493 strncpy(tmpnull, nulval,79);
494 tmpnull[79]='\0';
495 nulwidth = strlen(tmpnull);
496 } else {
497 strcpy(tmpnull, " ");
498 nulwidth = 1;
499 }
500
501 /* write the formated string for each value */
502 for (ii = 0; ii < nelem; ii++)
503 {
504 if (tcode == TBIT)
505 {
506 byteval = (char) darray[ii];
507
508 for (ll=0; ll < 8; ll++)
509 {
510 if ( ((unsigned char) (byteval << ll)) >> 7 )
511 *(array[ii] + ll) = '1';
512 else
513 *(array[ii] + ll) = '0';
514 }
515 *(array[ii] + 8) = '\0';
516 }
517 /* test for null value */
518 else if ( (nultyp == 1 && darray[ii] == DOUBLENULLVALUE) ||
519 (nultyp == 2 && nularray[ii]) )
520 {
521 *array[ii] = '\0';
522 if (dwidth < nulwidth)
523 strncat(array[ii], tmpnull, dwidth);
524 else
525 sprintf(array[ii],"%*s",dwidth,tmpnull);
526 }
527 else
528 {
529 if (intcol) {
530 snprintf(tmpstr, 400,cform, (int) darray[ii]);
531 } else {
532 snprintf(tmpstr, 400,cform, darray[ii]);
533 }
534
535 /* fill field with '*' if number is too wide */
536 dlen = strlen(tmpstr);
537 if (dlen > dwidth) {
538 memset(tmpstr, '*', dwidth);
539 }
540
541 *array[ii] = '\0';
542 strncat(array[ii], tmpstr, dwidth);
543 }
544 }
545
546 free(darray); /* free the memory */
547 }
548 return(*status);
549 }
550 /*--------------------------------------------------------------------------*/
ffgcdw(fitsfile * fptr,int colnum,int * width,int * status)551 int ffgcdw( fitsfile *fptr, /* I - FITS file pointer */
552 int colnum, /* I - number of column (1 = 1st col) */
553 int *width, /* O - display width */
554 int *status) /* IO - error status */
555 /*
556 Get Column Display Width.
557 */
558 {
559 tcolumn *colptr;
560 char *cptr;
561 char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], dispfmt[20];
562 int tcode, hdutype, tstatus, scaled;
563 double tscale;
564
565 if (*status > 0) /* inherit input status value if > 0 */
566 return(*status);
567
568 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
569 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
570
571 if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
572 {
573 snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
574 colnum);
575 ffpmsg(message);
576 return(*status = BAD_COL_NUM);
577 }
578
579 colptr = (fptr->Fptr)->tableptr; /* point to first column */
580 colptr += (colnum - 1); /* offset to correct column structure */
581 tcode = abs(colptr->tdatatype);
582
583 /* use the TDISPn keyword if it exists */
584 ffkeyn("TDISP", colnum, keyname, status);
585
586 *width = 0;
587 tstatus = 0;
588 if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
589 {
590 /* parse TDISPn get the display width */
591 cptr = dispfmt;
592 while(*cptr == ' ') /* skip leading blanks */
593 cptr++;
594
595 if (*cptr == 'A' || *cptr == 'a' ||
596 *cptr == 'I' || *cptr == 'i' ||
597 *cptr == 'O' || *cptr == 'o' ||
598 *cptr == 'Z' || *cptr == 'z' ||
599 *cptr == 'F' || *cptr == 'f' ||
600 *cptr == 'E' || *cptr == 'e' ||
601 *cptr == 'D' || *cptr == 'd' ||
602 *cptr == 'G' || *cptr == 'g')
603 {
604
605 while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
606 cptr++;
607
608 *width = atoi(cptr);
609 if (tcode >= TCOMPLEX)
610 *width = (2 * (*width)) + 3;
611 }
612 }
613
614 if (*width == 0)
615 {
616 /* no valid TDISPn keyword; use TFORMn instead */
617
618 ffkeyn("TFORM", colnum, keyname, status);
619 ffgkys(fptr, keyname, dispfmt, NULL, status);
620
621 /* check if column is scaled */
622 ffkeyn("TSCAL", colnum, keyname, status);
623 tstatus = 0;
624 scaled = 0;
625
626 if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
627 {
628 if (tscale != 1.0)
629 scaled = 1; /* yes, this is a scaled column */
630 }
631
632 if (scaled && tcode <= TSHORT)
633 {
634 /* scaled short integer col == float; default format is 14.6G */
635 *width = 14;
636 }
637 else if (scaled && tcode == TLONG)
638 {
639 /* scaled long integer col == double; default format is 23.15G */
640 *width = 23;
641 }
642 else if (scaled && tcode == TLONGLONG)
643 {
644 /* scaled long long integer col == double; default format is 23.15G */
645 *width = 23;
646 }
647
648 else
649 {
650 ffghdt(fptr, &hdutype, status); /* get type of table */
651 if (hdutype == ASCII_TBL)
652 {
653 /* parse TFORMn get the display width */
654 cptr = dispfmt;
655 while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
656 cptr++;
657
658 *width = atoi(cptr);
659 }
660 else
661 {
662 /* this is a binary table */
663 if (tcode == TBIT) /* 'X' */
664 *width = 8;
665 else if (tcode == TBYTE) /* 'B' */
666 *width = 4;
667 else if (tcode == TSHORT) /* 'I' */
668 *width = 6;
669 else if (tcode == TLONG) /* 'J' */
670 *width = 11;
671 else if (tcode == TLONGLONG) /* 'K' */
672 *width = 20;
673 else if (tcode == TFLOAT) /* 'E' */
674 *width = 14;
675 else if (tcode == TDOUBLE) /* 'D' */
676 *width = 23;
677 else if (tcode == TCOMPLEX) /* 'C' */
678 *width = 31;
679 else if (tcode == TDBLCOMPLEX) /* 'M' */
680 *width = 49;
681 else if (tcode == TLOGICAL) /* 'L' */
682 *width = 1;
683 else if (tcode == TSTRING) /* 'A' */
684 {
685 int typecode;
686 long int repeat = 0, rwidth = 0;
687 int gstatus = 0;
688
689 /* Deal with possible vector string with repeat / width by parsing
690 the TFORM=rAw keyword */
691 if (ffgtcl(fptr, colnum, &typecode, &repeat, &rwidth, &gstatus) == 0 &&
692 rwidth >= 1 && rwidth < repeat) {
693 *width = rwidth;
694
695 } else {
696
697 /* Hmmm, we couldn't parse the TFORM keyword by standard, so just do
698 simple parsing */
699 cptr = dispfmt;
700 while(!isdigit((int) *cptr) && *cptr != '\0')
701 cptr++;
702
703 *width = atoi(cptr);
704 }
705
706 if (*width < 1)
707 *width = 1; /* default is at least 1 column */
708 }
709 }
710 }
711 }
712 return(*status);
713 }
714 /*--------------------------------------------------------------------------*/
ffgcls2(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int nultyp,char * nulval,char ** array,char * nularray,int * anynul,int * status)715 int ffgcls2 ( fitsfile *fptr, /* I - FITS file pointer */
716 int colnum, /* I - number of column to read (1 = 1st col) */
717 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
718 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
719 LONGLONG nelem, /* I - number of strings to read */
720 int nultyp, /* I - null value handling code: */
721 /* 1: set undefined pixels = nulval */
722 /* 2: set nularray=1 for undefined pixels */
723 char *nulval, /* I - value for null pixels if nultyp = 1 */
724 char **array, /* O - array of values that are read */
725 char *nularray, /* O - array of flags = 1 if nultyp = 2 */
726 int *anynul, /* O - set to 1 if any values are null; else 0 */
727 int *status) /* IO - error status */
728 /*
729 Read an array of string values from a column in the current FITS HDU.
730 */
731 {
732 double dtemp;
733 long nullen;
734 int tcode, maxelem, hdutype, nulcheck;
735 long twidth, incre;
736 long ii, jj, ntodo;
737 LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
738 double scale, zero;
739 char tform[20];
740 char message[FLEN_ERRMSG];
741 char snull[20]; /* the FITS null value */
742 tcolumn *colptr;
743
744 double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
745 char *buffer, *arrayptr;
746
747 if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */
748 return(*status);
749
750 if (fptr->HDUposition != (fptr->Fptr)->curhdu)
751 ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
752
753 if (anynul)
754 *anynul = 0;
755
756 if (nultyp == 2)
757 memset(nularray, 0, (size_t) nelem); /* initialize nullarray */
758
759 /*---------------------------------------------------*/
760 /* Check input and get parameters about the column: */
761 /*---------------------------------------------------*/
762 if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
763 {
764 snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
765 colnum);
766 ffpmsg(message);
767 return(*status = BAD_COL_NUM);
768 }
769
770 colptr = (fptr->Fptr)->tableptr; /* point to first column */
771 colptr += (colnum - 1); /* offset to correct column structure */
772 tcode = colptr->tdatatype;
773
774 if (tcode == -TSTRING) /* variable length column in a binary table? */
775 {
776 /* only read a single string; ignore value of firstelem */
777
778 if (ffgcprll( fptr, colnum, firstrow, 1, 1, 0, &scale, &zero,
779 tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
780 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
781 return(*status);
782
783 remain = 1;
784 twidth = (long) repeat;
785 }
786 else if (tcode == TSTRING)
787 {
788 if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
789 tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
790 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
791 return(*status);
792
793 /* if string length is greater than a FITS block (2880 char) then must */
794 /* only read 1 string at a time, to force reading by ffgbyt instead of */
795 /* ffgbytoff (ffgbytoff can't handle this case) */
796 if (twidth > IOBUFLEN) {
797 maxelem = 1;
798 incre = twidth;
799 repeat = 1;
800 }
801
802 remain = nelem;
803 }
804 else
805 return(*status = NOT_ASCII_COL);
806
807 nullen = strlen(snull); /* length of the undefined pixel string */
808 if (nullen == 0)
809 nullen = 1;
810
811 /*------------------------------------------------------------------*/
812 /* Decide whether to check for null values in the input FITS file: */
813 /*------------------------------------------------------------------*/
814 nulcheck = nultyp; /* by default check for null values in the FITS file */
815
816 if (nultyp == 1 && nulval == 0)
817 nulcheck = 0; /* calling routine does not want to check for nulls */
818
819 else if (nultyp == 1 && nulval && nulval[0] == 0)
820 nulcheck = 0; /* calling routine does not want to check for nulls */
821
822 else if (snull[0] == ASCII_NULL_UNDEFINED)
823 nulcheck = 0; /* null value string in ASCII table not defined */
824
825 else if (nullen > twidth)
826 nulcheck = 0; /* null value string is longer than width of column */
827 /* thus impossible for any column elements to = null */
828
829 /*---------------------------------------------------------------------*/
830 /* Now read the strings one at a time from the FITS column. */
831 /*---------------------------------------------------------------------*/
832 next = 0; /* next element in array to be read */
833 rownum = 0; /* row number, relative to firstrow */
834
835 while (remain)
836 {
837 /* limit the number of pixels to process at one time to the number that
838 will fit in the buffer space or to the number of pixels that remain
839 in the current vector, which ever is smaller.
840 */
841 ntodo = (long) minvalue(remain, maxelem);
842 ntodo = (long) minvalue(ntodo, (repeat - elemnum));
843
844 readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
845 ffmbyt(fptr, readptr, REPORT_EOF, status); /* move to read position */
846
847 /* read the array of strings from the FITS file into the buffer */
848
849 if (incre == twidth)
850 ffgbyt(fptr, ntodo * twidth, cbuff, status);
851 else
852 ffgbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
853
854 /* copy from the buffer into the user's array of strings */
855 /* work backwards from last char of last string to 1st char of 1st */
856
857 buffer = ((char *) cbuff) + (ntodo * twidth) - 1;
858
859 for (ii = (long) (next + ntodo - 1); ii >= next; ii--)
860 {
861 arrayptr = array[ii] + twidth - 1;
862
863 for (jj = twidth - 1; jj > 0; jj--) /* ignore trailing blanks */
864 {
865 if (*buffer == ' ')
866 {
867 buffer--;
868 arrayptr--;
869 }
870 else
871 break;
872 }
873 *(arrayptr + 1) = 0; /* write the string terminator */
874
875 for (; jj >= 0; jj--) /* copy the string itself */
876 {
877 *arrayptr = *buffer;
878 buffer--;
879 arrayptr--;
880 }
881
882 /* check if null value is defined, and if the */
883 /* column string is identical to the null string */
884 if (nulcheck && !strncmp(snull, array[ii], nullen) )
885 {
886 *anynul = 1; /* this is a null value */
887 if (nultyp == 1) {
888
889 if (nulval)
890 strcpy(array[ii], nulval);
891 else
892 strcpy(array[ii], " ");
893
894 } else
895 nularray[ii] = 1;
896 }
897 }
898
899 if (*status > 0) /* test for error during previous read operation */
900 {
901 dtemp = (double) next;
902 snprintf(message,FLEN_ERRMSG,
903 "Error reading elements %.0f thru %.0f of data array (ffpcls).",
904 dtemp+1., dtemp+ntodo);
905
906 ffpmsg(message);
907 return(*status);
908 }
909
910 /*--------------------------------------------*/
911 /* increment the counters for the next loop */
912 /*--------------------------------------------*/
913 next += ntodo;
914 remain -= ntodo;
915 if (remain)
916 {
917 elemnum += ntodo;
918 if (elemnum == repeat) /* completed a row; start on next row */
919 {
920 elemnum = 0;
921 rownum++;
922 }
923 }
924 } /* End of main while Loop */
925
926 return(*status);
927 }
928
929