WCSLIB: fitshdr.h Source File

WCSLIB 8.9

Loading...
Searching...
No Matches
fitshdr.h
Go to the documentation of this file.
1/*============================================================================
2 WCSLIB 8.9 - an implementation of the FITS WCS standard.
3 Copyright (C) 1995-2026, Mark Calabretta
4
5 This file is part of WCSLIB.
6
7 WCSLIB is free software: you can redistribute it and/or modify it under the
8 terms of the GNU Lesser General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or (at your option)
10 any later version.
11
12 WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with WCSLIB. If not, see http://www.gnu.org/licenses.
19
20 Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
21 http://www.atnf.csiro.au/computing/software/wcs
22 $Id: fitshdr.h,v 8.9 2026/06/18 13:00:03 mcalabre Exp $
23*=============================================================================
24*
25* WCSLIB 8.9 - C routines that implement the FITS World Coordinate System
26* (WCS) standard. Refer to the README file provided with WCSLIB for an
27* overview of the library.
28*
29*
30* Summary of the fitshdr routines
31* -------------------------------
32* The Flexible Image Transport System (FITS), is a data format widely used in
33* astronomy for data interchange and archive. It is described in
34*
35= "Definition of the Flexible Image Transport System (FITS), version 3.0",
36= Pence, W.D., Chiappetti, L., Page, C.G., Shaw, R.A., & Stobie, E. 2010,
37= A&A, 524, A42 - http://dx.doi.org/10.1051/0004-6361/201015362
38*
39* See also http://fits.gsfc.nasa.gov
40*
41* fitshdr() is a generic FITS header parser provided to handle keyrecords that
42* are ignored by the WCS header parsers, wcspih() and wcsbth(). Typically the
43* latter may be set to remove WCS keyrecords from a header leaving fitshdr()
44* to handle the remainder.
45*
46*
47* fitshdr() - FITS header parser routine
48* --------------------------------------
49* fitshdr() parses a character array containing a FITS header, extracting
50* all keywords and their values into an array of fitskey structs.
51*
52* Given:
53* header const char []
54* Character array containing the (entire) FITS header,
55* for example, as might be obtained conveniently via the
56* CFITSIO routine fits_hdr2str().
57*
58* Each header "keyrecord" (formerly "card image")
59* consists of exactly 80 7-bit ASCII printing characters
60* in the range 0x20 to 0x7e (which excludes NUL, BS,
61* TAB, LF, FF and CR) especially noting that the
62* keyrecords are NOT null-terminated.
63*
64* nkeyrec int Number of keyrecords in header[].
65*
66* nkeyids int Number of entries in keyids[].
67*
68* Given and returned:
69* keyids struct fitskeyid []
70* While all keywords are extracted from the header,
71* keyids[] provides a convienient way of indexing them.
72* The fitskeyid struct contains three members;
73* fitskeyid::name must be set by the user while
74* fitskeyid::count and fitskeyid::idx are returned by
75* fitshdr(). All matched keywords will have their
76* fitskey::keyno member negated.
77*
78* Returned:
79* nreject int* Number of header keyrecords rejected for syntax
80* errors.
81*
82* keys struct fitskey**
83* Pointer to an array of nkeyrec fitskey structs
84* containing all keywords and keyvalues extracted from
85* the header.
86*
87* Memory for the array is allocated by fitshdr() and
88* this must be freed by the user. See wcsdealloc().
89*
90* Function return value:
91* int Status return value:
92* 0: Success.
93* 1: Null fitskey pointer passed.
94* 2: Memory allocation failed.
95* 3: Fatal error returned by Flex parser.
96* 4: Unrecognised data type.
97*
98* Notes:
99* 1: Keyword parsing is done in accordance with the syntax defined by
100* NOST 100-2.0, noting the following points in particular:
101*
102* a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
103* 1-8, blank-filled with no embedded spaces, composed only of the
104* ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
105*
106* fitshdr() accepts any characters in columns 1-8 but flags keywords
107* that do not conform to standard syntax.
108*
109* b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
110* occurring in columns 9 and 10. If these are absent then the
111* keyword has no value and columns 9-80 may contain any ASCII text
112* (but see note 2 for CONTINUE keyrecords). This is copied to the
113* comment member of the fitskey struct.
114*
115* c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
116* value if the value/comment field, columns 11-80, consists entirely
117* of spaces, possibly followed by a comment.
118*
119* d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
120* not significant and the parser always removes them. A string
121* containing nothing but blanks will be replaced with a single
122* blank.
123*
124* Sect. 5.2.1 also states that a quote character (') in a string
125* value is to be represented by two successive quote characters and
126* the parser removes the repeated quote.
127*
128* e: The parser recognizes free-format character (NOST 100-2.0,
129* Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
130* (Sect. 5.2.4) for all keywords.
131*
132* f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
133* except indirectly in limiting it to 70 digits. The parser will
134* translate an integer keyvalue to a 32-bit signed integer if it
135* lies in the range -2147483648 to +2147483647, otherwise it
136* interprets it as a 64-bit signed integer if possible, or else a
137* "very long" integer (see fitskey::type).
138*
139* g: END not followed by 77 blanks is not considered to be a legitimate
140* end keyrecord.
141*
142* 2: The parser supports a generalization of the OGIP Long String Keyvalue
143* Convention (v1.0) whereby strings may be continued onto successive
144* header keyrecords. A keyrecord contains a segment of a continued
145* string if and only if
146*
147* a: it contains the pseudo-keyword CONTINUE,
148*
149* b: columns 9 and 10 are both blank,
150*
151* c: columns 11 to 80 contain what would be considered a valid string
152* keyvalue, including optional keycomment, if column 9 had contained
153* '=',
154*
155* d: the previous keyrecord contained either a valid string keyvalue or
156* a valid CONTINUE keyrecord.
157*
158* If any of these conditions is violated, the keyrecord is considered in
159* isolation.
160*
161* Syntax errors in keycomments in a continued string are treated more
162* permissively than usual; the '/' delimiter may be omitted provided that
163* parsing of the string keyvalue is not compromised. However, the
164* FITSHDR_COMMENT status bit will be set for the keyrecord (see
165* fitskey::status).
166*
167* As for normal strings, trailing blanks in a continued string are not
168* significant.
169*
170* In the OGIP convention "the '&' character is used as the last non-blank
171* character of the string to indicate that the string is (probably)
172* continued on the following keyword". This additional syntax is not
173* required by fitshdr(), but if '&' does occur as the last non-blank
174* character of a continued string keyvalue then it will be removed, along
175* with any trailing blanks. However, blanks that occur before the '&'
176* will be preserved.
177*
178*
179* fitskeyid struct - Keyword indexing
180* -----------------------------------
181* fitshdr() uses the fitskeyid struct to return indexing information for
182* specified keywords. The struct contains three members, the first of which,
183* fitskeyid::name, must be set by the user with the remainder returned by
184* fitshdr().
185*
186* char name[12]:
187* (Given) Name of the required keyword. This is to be set by the user;
188* the '.' character may be used for wildcarding. Trailing blanks will be
189* replaced with nulls.
190*
191* int count:
192* (Returned) The number of matches found for the keyword.
193*
194* int idx[2]:
195* (Returned) Indices into keys[], the array of fitskey structs returned by
196* fitshdr(). Note that these are 0-relative array indices, not keyrecord
197* numbers.
198*
199* If the keyword is found in the header the first index will be set to the
200* array index of its first occurrence, otherwise it will be set to -1.
201*
202* If multiples of the keyword are found, the second index will be set to
203* the array index of its last occurrence, otherwise it will be set to -1.
204*
205*
206* fitskey struct - Keyword/value information
207* ------------------------------------------
208* fitshdr() returns an array of fitskey structs, each of which contains the
209* result of parsing one FITS header keyrecord. All members of the fitskey
210* struct are returned by fitshdr(), none are given by the user.
211*
212* int keyno
213* (Returned) Keyrecord number (1-relative) in the array passed as input to
214* fitshdr(). This will be negated if the keyword matched any specified in
215* the keyids[] index.
216*
217* int keyid
218* (Returned) Index into the first entry in keyids[] with which the
219* keyrecord matches, else -1.
220*
221* int status
222* (Returned) Status flag bit-vector for the header keyrecord employing the
223* following bit masks defined as preprocessor macros:
224*
225* - FITSHDR_KEYWORD: Illegal keyword syntax.
226* - FITSHDR_KEYVALUE: Illegal keyvalue syntax.
227* - FITSHDR_COMMENT: Illegal keycomment syntax.
228* - FITSHDR_KEYREC: Illegal keyrecord, e.g. an END keyrecord with
229* trailing text.
230* - FITSHDR_TRAILER: Keyrecord following a valid END keyrecord.
231*
232* The header keyrecord is syntactically correct if no bits are set.
233*
234* char keyword[12]
235* (Returned) Keyword name, null-filled for keywords of less than eight
236* characters (trailing blanks replaced by nulls).
237*
238* Use
239*
240= sprintf(dst, "%.8s", keyword)
241*
242* to copy it to a character array with null-termination, or
243*
244= sprintf(dst, "%8.8s", keyword)
245*
246* to blank-fill to eight characters followed by null-termination.
247*
248* int type
249* (Returned) Keyvalue data type:
250* - 0: No keyvalue (both the value and type are undefined).
251* - 1: Logical, represented as int.
252* - 2: 32-bit signed integer.
253* - 3: 64-bit signed integer (see below).
254* - 4: Very long integer (see below).
255* - 5: Floating point (stored as double).
256* - 6: Integer complex (stored as double[2]).
257* - 7: Floating point complex (stored as double[2]).
258* - 8: String.
259* - 8+10*n: Continued string (described below and in fitshdr() note 2).
260*
261* A negative type indicates that a syntax error was encountered when
262* attempting to parse a keyvalue of the particular type.
263*
264* Comments on particular data types:
265* - 64-bit signed integers lie in the range
266*
267= (-9223372036854775808 <= int64 < -2147483648) ||
268= (+2147483647 < int64 <= +9223372036854775807)
269*
270* A native 64-bit data type may be defined via preprocessor macro
271* WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
272* will be typedef'd to 'int64' here. If WCSLIB_INT64 is not set, then
273* int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
274* computed as
275*
276= ((keyvalue.k[2]) * 1000000000 +
277= keyvalue.k[1]) * 1000000000 +
278= keyvalue.k[0]
279*
280* and may reported via
281*
282= if (keyvalue.k[2]) {
283= printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
284= abs(keyvalue.k[0]));
285= } else {
286= printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
287= }
288*
289* where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
290* +999999999.
291*
292* - Very long integers, up to 70 decimal digits in length, are encoded
293* in keyvalue.l as an array of int[8], each of which stores 9 decimal
294* digits. fitskey::keyvalue is to be computed as
295*
296= (((((((keyvalue.l[7]) * 1000000000 +
297= keyvalue.l[6]) * 1000000000 +
298= keyvalue.l[5]) * 1000000000 +
299= keyvalue.l[4]) * 1000000000 +
300= keyvalue.l[3]) * 1000000000 +
301= keyvalue.l[2]) * 1000000000 +
302= keyvalue.l[1]) * 1000000000 +
303= keyvalue.l[0]
304*
305* - Continued strings are not reconstructed, they remain split over
306* successive fitskey structs in the keys[] array returned by
307* fitshdr(). fitskey::keyvalue data type, 8 + 10n, indicates the
308* segment number, n, in the continuation.
309*
310* int padding
311* (An unused variable inserted for alignment purposes only.)
312*
313* union keyvalue
314* (Returned) A union comprised of
315*
316* - fitskey::i,
317* - fitskey::k,
318* - fitskey::l,
319* - fitskey::f,
320* - fitskey::c,
321* - fitskey::s,
322*
323* used by the fitskey struct to contain the value associated with a
324* keyword.
325*
326* int i
327* (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
328* (fitskey::type == 2) data types in the fitskey::keyvalue union.
329*
330* int64 k
331* (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
332* fitskey::keyvalue union.
333*
334* int l[8]
335* (Returned) Very long integer (fitskey::type == 4) data type in the
336* fitskey::keyvalue union.
337*
338* double f
339* (Returned) Floating point (fitskey::type == 5) data type in the
340* fitskey::keyvalue union.
341*
342* double c[2]
343* (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
344* data types in the fitskey::keyvalue union.
345*
346* char s[72]
347* (Returned) Null-terminated string (fitskey::type == 8) data type in the
348* fitskey::keyvalue union.
349*
350* int ulen
351* (Returned) Where a keycomment contains a units string in the standard
352* form, e.g. [m/s], the ulen member indicates its length, inclusive of
353* square brackets. Otherwise ulen is zero.
354*
355* char comment[84]
356* (Returned) Keycomment, i.e. comment associated with the keyword or, for
357* keyrecords rejected because of syntax errors, the compete keyrecord
358* itself with null-termination.
359*
360* Comments are null-terminated with trailing spaces removed. Leading
361* spaces are also removed from keycomments (i.e. those immediately
362* following the '/' character), but not from COMMENT or HISTORY keyrecords
363* or keyrecords without a value indicator ("= " in columns 9-80).
364*
365*
366* Global variable: const char *fitshdr_errmsg[] - Status return messages
367* ----------------------------------------------------------------------
368* Error messages to match the status value returned from each function.
369*
370*===========================================================================*/
371
372#ifndef WCSLIB_FITSHDR
373#define WCSLIB_FITSHDR
374
375#include "wcsconfig.h"
376
377#ifdef __cplusplus
378extern "C" {
379#endif
380
381#define FITSHDR_KEYWORD 0x01
382#define FITSHDR_KEYVALUE 0x02
383#define FITSHDR_COMMENT 0x04
384#define FITSHDR_KEYREC 0x08
385#define FITSHDR_CARD 0x08 // Alias for backwards compatibility.
386#define FITSHDR_TRAILER 0x10
387
388
389extern const char *fitshdr_errmsg[];
390
391 enum fitshdr_errmsg_enum {
392 FITSHDRERR_SUCCESS = 0, // Success.
393 FITSHDRERR_NULL_POINTER = 1, // Null fitskey pointer passed.
394 FITSHDRERR_MEMORY = 2, // Memory allocation failed.
395 FITSHDRERR_FLEX_PARSER = 3, // Fatal error returned by Flex parser.
396 FITSHDRERR_DATA_TYPE = 4 // Unrecognised data type.
397};
398
399#ifdef WCSLIB_INT64
400 typedef WCSLIB_INT64 int64;
401#else
402 typedef int int64[3];
403#endif
404
405
406// Struct used for indexing the keywords.
407 struct fitskeyid {
408 char name[12]; // Keyword name, null-terminated.
409 int count; // Number of occurrences of keyword.
410 int idx[2]; // Indices into fitskey array.
411};
412
413// Size of the fitskeyid struct in int units, used by the Fortran wrappers.
414#define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
415
416
417// Struct used for storing FITS keywords.
418 struct fitskey {
419 int keyno; // Header keyrecord sequence number (1-rel).
420 int keyid; // Index into fitskeyid[].
421 int status; // Header keyrecord status bit flags.
422 char keyword[12]; // Keyword name, null-filled.
423 int type; // Keyvalue type (see above).
424 int padding; // (Dummy inserted for alignment purposes.)
425 union {
426 int i; // 32-bit integer and logical values.
427 int64 k; // 64-bit integer values.
428 int l[8]; // Very long signed integer values.
429 double f; // Floating point values.
430 double c[2]; // Complex values.
431 char s[72]; // String values, null-terminated.
432 } keyvalue; // Keyvalue.
433 int ulen; // Length of units string.
434 char comment[84]; // Comment (or keyrecord), null-terminated.
435};
436
437// Size of the fitskey struct in int units, used by the Fortran wrappers.
438#define KEYLEN (sizeof(struct fitskey)/sizeof(int))
439
440
441 int fitshdr(const char header[], int nkeyrec, int nkeyids,
442 struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
443
444
445#ifdef __cplusplus
446}
447#endif
448
449#endif // WCSLIB_FITSHDR
fitshdr_errmsg
const char * fitshdr_errmsg[]
Status return messages.
fitshdr_errmsg_enum
fitshdr_errmsg_enum
Definition fitshdr.h:391
FITSHDRERR_FLEX_PARSER
@ FITSHDRERR_FLEX_PARSER
Definition fitshdr.h:395
FITSHDRERR_NULL_POINTER
@ FITSHDRERR_NULL_POINTER
Definition fitshdr.h:393
FITSHDRERR_SUCCESS
@ FITSHDRERR_SUCCESS
Definition fitshdr.h:392
FITSHDRERR_DATA_TYPE
@ FITSHDRERR_DATA_TYPE
Definition fitshdr.h:396
FITSHDRERR_MEMORY
@ FITSHDRERR_MEMORY
Definition fitshdr.h:394
int64
int int64[3]
64-bit signed integer data type.
Definition fitshdr.h:402
fitshdr
int fitshdr(const char header[], int nkeyrec, int nkeyids, struct fitskeyid keyids[], int *nreject, struct fitskey **keys)
FITS header parser routine.
fitskey
Keyword/value information.
Definition fitshdr.h:418
fitskey::comment
char comment[84]
Definition fitshdr.h:434
fitskey::padding
int padding
Definition fitshdr.h:424
fitskey::keyno
int keyno
Definition fitshdr.h:419
fitskey::keyvalue
union fitskey::@167365156227154041246270050064242147120347336341 keyvalue
fitskey::keyword
char keyword[12]
Definition fitshdr.h:422
fitskey::c
double c[2]
Definition fitshdr.h:430
fitskey::i
int i
Definition fitshdr.h:426
fitskey::status
int status
Definition fitshdr.h:421
fitskey::l
int l[8]
Definition fitshdr.h:428
fitskey::ulen
int ulen
Definition fitshdr.h:433
fitskey::type
int type
Definition fitshdr.h:423
fitskey::f
double f
Definition fitshdr.h:429
fitskey::k
int64 k
Definition fitshdr.h:427
fitskey::keyid
int keyid
Definition fitshdr.h:420
fitskey::s
char s[72]
Definition fitshdr.h:431
fitskeyid
Keyword indexing.
Definition fitshdr.h:407
fitskeyid::name
char name[12]
Definition fitshdr.h:408
fitskeyid::count
int count
Definition fitshdr.h:409
fitskeyid::idx
int idx[2]
Definition fitshdr.h:410