fits.h

Go to the documentation of this file.
00001 //# fits.h:
00002 //# Copyright (C) 1993,1994,1995,1996,1997,1999,2000,2001,2003,2004
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //# 
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //# 
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //# 
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //# 
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id$
00027 
00028 # if !defined(AIPS_FITS)
00029 # define AIPS_FITS
00030 
00031 //# Note that aips.h has to come first for the correct definition of off_t.
00032 # include <casacore/casa/aips.h>
00033 # include <stdlib.h>
00034 # include <ctype.h>
00035 # include <casacore/casa/iostream.h>
00036 # include <casacore/casa/BasicSL/Complex.h>
00037 # include <casacore/casa/BasicSL/IComplex.h>
00038 # include <casacore/fits/FITS/FITSError.h>
00039 
00040 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00041 
00042 //# All FITS code seems to assume longs are 4 bytes. To take care of machines 
00043 //# for which this isn't true use FitsLong instead of Long in the FITS code
00044 //# where it matters.
00045 # if (defined(__alpha) || defined(__sgi) || defined(__x86_64__))
00046     typedef Int FitsLong;
00047 # else
00048     typedef Long FitsLong;
00049 # endif 
00050 //# recovered by GYL
00051 
00052 //# Forward declarations
00053 class ReservedFitsKeywordCollection;
00054 class FitsNameResult;
00055 class FitsValueResult;
00056 class FitsKeyword;
00057 class FitsParse;
00058 
00059 //<summary> FITS templated helper class </summary>
00060 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00061 // </reviewed>
00062 //<synopsis>
00063 // NoConvert is a template class that is not intended for
00064 // general use, it is used internally.
00065 //</synopsis>
00066 
00067 template <class TYPE>
00068 class NoConvert {
00069     public:
00070         NoConvert() { }
00071         void operator = (int) {; }
00072 };
00073 
00074 //<summary> FITS helper class </summary>
00075 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00076 // </reviewed>
00077 //<synopsis>
00078 // FitsLogical is a helper class that is not intended for
00079 // general use. 
00080 //</synopsis>
00081 //<example>
00082 // Here is an example of the FitsLogical class. 
00083 //<srcblock>
00084 //      FitsLogical x;
00085 //      FitsLogical y(True);
00086 //      FitsLogical z = x;
00087 //      ...
00088 //      x = y; y = False; x.undefine();
00089 //      Bool b;
00090 //      if (x.isdefined())
00091 //              b = x;
00092 //      b = y;  If y is undefined, b will be false.
00093 //</srcblock>
00094 //</example>
00095 class FitsLogical {
00096         friend ostream & operator << (ostream &o, const FitsLogical &);
00097     public:
00098         FitsLogical() : v('\0') { }
00099         FitsLogical(Bool x) { v = (x == True ? 'T' : 'F'); }
00100         FitsLogical(const FitsLogical &x) : v(x.v) { }
00101         FitsLogical & operator = (const FitsLogical &x) { 
00102                 v = x.v; return *this; }
00103         FitsLogical & operator = (Bool x) { 
00104                 v = (x == True ? 'T' : 'F'); return *this; }
00105         Bool isdefined() const { return v == '\0' ? True : False; }
00106         void undefine() { v = '\0'; }
00107         operator Bool() { return (v == 'T' ? True : False); }
00108     protected:
00109         char v;
00110 };
00111 
00112 //<summary> helper class for FITS Binary Tables </summary>
00113 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00114 // </reviewed>
00115 //<synopsis>
00116 // This class is not intended for general use.  It only has meaning
00117 // in the context of FITS Binary tables.  There its use is incorporated
00118 // into the concept of a FitsField, where FitsBit is given a specialized
00119 // interpretation.
00120 //</synopsis>
00121 
00122 class FitsBit {
00123     public:
00124         FitsBit() : bit_array(0) { }
00125         FitsBit(unsigned char x) : bit_array(x) { }
00126         FitsBit(const FitsBit &x) : bit_array(x.bit_array) { }
00127         FitsBit & operator = (const FitsBit &x) { 
00128                 bit_array = x.bit_array; return *this; }
00129         FitsBit & operator = (unsigned char x) { bit_array = x; return *this; }
00130         operator unsigned char() { return bit_array; }
00131     protected:
00132         unsigned char bit_array;
00133 };
00134 
00135 //<summary>  Variable Length Array Descriptor </summary>
00136 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00137 // </reviewed>
00138 
00139 class FitsVADesc { 
00140         friend ostream & operator << (ostream &o, const FitsVADesc &);
00141     public:
00142         FitsVADesc() : no_elements(0), rel_offset(0) { }
00143         FitsVADesc(const FitsVADesc &x) :
00144                 no_elements(x.no_elements), rel_offset(x.rel_offset) { }
00145         FitsVADesc & operator = (const FitsVADesc &x) {
00146                 no_elements= x.no_elements;
00147                 rel_offset = x.rel_offset; return *this; }
00148         FitsVADesc(int n, int o) : no_elements(n), rel_offset(o) { }
00149         void set(int n, int o) { no_elements = n; rel_offset = o; }
00150         int num() const         { return no_elements; }
00151         int offset() const      { return rel_offset; }
00152     protected:
00153         int no_elements;
00154         int rel_offset;
00155 };
00156 
00157 //<summary> static functions and enumerations </summary>
00158 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00159 // </reviewed>
00160 //<synopsis>
00161 // Many of the static functions are utility functions used internally in the
00162 // implementation of the member functions of the FITS classes. They are placed
00163 // in a single class to encapsulate them and to avoid adding many names to the 
00164 // global name space. More important, from the user's perspective, are the
00165 // enumerations. They form the basic vocabulary of a FITS application. For example,
00166 // instead of referring to the FITS <src>NAXIS</src> keyword, 
00167 // <src>FITS::NAXIS</src> should be used
00168 //</synopsis>
00169 
00170 class FITS {
00171     public:
00172 
00173     // FITS I/O Error message types
00174 
00175         // Basic FITS Data Types for keywords and data
00176         enum ValueType {
00177             NOVALUE = 0, LOGICAL = 1, BIT = 2, CHAR = 3, BYTE = 4, 
00178             SHORT = 5, LONG = 6, FLOAT = 7, DOUBLE = 8, COMPLEX = 9, 
00179             ICOMPLEX = 10, DCOMPLEX = 11, VADESC = 12,
00180             STRING, FSTRING, REAL
00181         }; // REAL means either FLOAT or DOUBLE
00182            // STRING and FSTRING are used internally in parsing keywords
00183 
00184         static  FITS::ValueType getfitstype(NoConvert<FitsLogical> x) {
00185                 x=0; return FITS::LOGICAL; }
00186         static  FITS::ValueType getfitstype(NoConvert<FitsBit> x) {
00187                 x=0; return FITS::BIT; }
00188         static  FITS::ValueType getfitstype(NoConvert<char> x) {
00189                 x=0; return FITS::CHAR; }
00190         static  FITS::ValueType getfitstype(NoConvert<unsigned char> x) {
00191                 x=0; return FITS::BYTE; }
00192         static  FITS::ValueType getfitstype(NoConvert<short> x) {
00193                 x=0; return FITS::SHORT; }
00194         static  FITS::ValueType getfitstype(NoConvert<Int> x) {
00195                 x=0; return FITS::LONG; }
00196         static  FITS::ValueType getfitstype(NoConvert<long> x) {
00197                 x=0; return FITS::LONG; }
00198         static  FITS::ValueType getfitstype(NoConvert<float> x) {
00199                 x=0; return FITS::FLOAT; }
00200         static  FITS::ValueType getfitstype(NoConvert<double> x) {
00201                 x=0; return FITS::DOUBLE; }
00202         static  FITS::ValueType getfitstype(NoConvert<Complex> x) {
00203                 x=0; return FITS::COMPLEX; }
00204         static  FITS::ValueType getfitstype(NoConvert<IComplex> x) {
00205                 x=0; return FITS::ICOMPLEX; }   
00206         static  FITS::ValueType getfitstype(NoConvert<DComplex> x) {
00207                 x=0; return FITS::DCOMPLEX; }
00208         static  FITS::ValueType getfitstype(NoConvert<FitsVADesc> x) {
00209                 x=0; return FITS::VADESC; }
00210 
00211         static  int fitssize(FITS::ValueType t);
00212         static  int localsize(FITS::ValueType t);
00213 
00214         // data conversion routines: FITS - local
00215         static void f2l(FitsLogical *,void *,int);
00216         static void l2f(void *,FitsLogical *,int);
00217         static void f2l(FitsBit *,void *,int);
00218         static void l2f(void *,FitsBit *,int);
00219         static void f2l(char *,void *,int);
00220         static void l2f(void *,char *,int);
00221         static void f2l(unsigned char *,void *,int);
00222         static void l2f(void *,unsigned char *,int);
00223         static void f2l(short *,void *,int);
00224         static void l2f(void *,short *,int);
00225         static void f2l(Int *,void *,int);
00226         static void l2f(void *,Int *,int);
00227         static void f2l(long *,void *,int);
00228         static void l2f(void *,long *,int);
00229         static void f2l(float *,void *,int);
00230         static void l2f(void *,float *,int);
00231         static void f2l(double *,void *,int);
00232         static void l2f(void *,double *,int);
00233         static void f2l(Complex *,void *,int);
00234         static void l2f(void *,Complex *,int);
00235         static void f2l(IComplex *,void *,int);
00236         static void l2f(void *,IComplex *,int);
00237         static void f2l(DComplex *,void *,int);
00238         static void l2f(void *,DComplex *,int);
00239         static void f2l(FitsVADesc *,void *,int);
00240         static void l2f(void *,FitsVADesc *,int);
00241         static void swap2(void *, void *, int);
00242         static void swap4(void *, void *, int);
00243         static void swap8(void *, void *, int);
00244 
00245         // FITS Reserved Names. PZERO is named strangely because it can conflict with
00246         // a standard #define in sys/param.h.
00247         enum ReservedName {
00248             USER_DEF, AUTHOR,   BITPIX,   BLANK,    BLOCKED,  BSCALE,
00249             BUNIT,    BZERO,    CDELT,    COMMENT,  CROTA,    CRPIX,
00250             CRVAL,    CTYPE,    DATAMAX,  DATAMIN,  DATE,     DATE_OBS,
00251             END,      EPOCH,    EQUINOX,  EXTEND,   EXTLEVEL, EXTNAME,
00252             EXTVER,   GCOUNT,   GROUPS,   HISTORY,  INSTRUME, NAXIS,
00253             OBJECT,   OBSERVER, ORIGIN,   PCOUNT,   PSCAL,    PTYPE,
00254             PZERO_FITS,    REFERENC, SIMPLE,   SPACES,   TBCOL,    TDIM,
00255             TDISP,    TELESCOP, TFIELDS,  TFORM,    THEAP,    TNULL,
00256             TSCAL,    TTYPE,    TUNIT,    TZERO,    XTENSION, ERRWORD,
00257             ALTRPIX, DATE_MAP
00258         };
00259 
00260         // Types of FITS Records
00261         enum FitsRecType { 
00262             InitialState, BadBeginningRecord, HDURecord,
00263             UnrecognizableRecord, SpecialRecord, EndOfFile 
00264         };
00265 
00266         // Supported FITS Physical Devices
00267         enum FitsDevice { 
00268             Disk, Std, Tape9
00269         };
00270 
00271         // Types of FITS Header-Data Units
00272         enum HDUType {
00273             NotAHDU, PrimaryArrayHDU, PrimaryGroupHDU, AsciiTableHDU,
00274             BinaryTableHDU, ImageExtensionHDU, UnknownExtensionHDU,
00275             PrimaryTableHDU
00276         };
00277 
00278         // Options on FITS array manipulations
00279         enum FitsArrayOption { NoOpt = 0, CtoF = 1, FtoC = 2};
00280 
00281         static ReservedFitsKeywordCollection &ResWord;
00282         static void valstr(ostream &o, const ValueType &ty, const void *val);
00283         static Bool isa_digit(char c);
00284         static int digit2bin(char c);
00285         static Bool isa_text(char c);
00286         static Bool isa_letter(char);
00287         static int letter2bin(char);
00288         static void fstr2str(char *, const char *, int);
00289         static int str2fstr(char *, const char *, int);
00290         static void get_name(const char *s, int len, FitsNameResult &result);
00291         static int get_value_id(const char *s, int l, int &pos);
00292         static void get_value(const char *s, int len, FitsValueResult &result);
00293         static int trim_comment(const char *s, int len);
00294         static int chk_comment(const char *s, int len);
00295         static int get_comment(const char *s, int len, int &begpos);
00296         static void get_numeric(const char *s, int len, FitsValueResult &result);
00297     // utility function to parse the binary table variable array
00298     // column (i.e. uses the heap) of the form nPt(dddd) where n
00299     // is either 0 or 1, t is one of the standard FITS binary table
00300     // column types and dddd is the maximum number of elements used
00301     // by this column.  If there is a format error in the input
00302     // string (*s), then valType will have the value NOVALUE and
00303     // maxelem will be -1.
00304         static void parse_vatform(const char *s, FITS::ValueType &valType,
00305                                   int &maxelem);
00306         static const Int minInt;
00307         static const Int maxInt;
00308         static const float minfloat;
00309         static const float maxfloat;
00310         static const double mindouble;
00311         static const double maxdouble;
00312 
00313     private:
00314         FITS();
00315         static double tenpowerD[309];
00316         static float tenpowerF[39];
00317         static const int minfltexp;
00318         static const int maxfltexp;
00319         static const int mindblexp;
00320         static const int maxdblexp;
00321         static const int maxsigdigits;
00322         static const int maxdigl; // max digits in a long
00323         static const int maxexpdig; // max digits in an exponent
00324         static double tenD(Int, int);
00325         static float tenF(Int, int);
00326         static int ckaccum(double &, Int, int);
00327         static int ckaccum(float &, Int, int);
00328 };
00329 
00330 inline FITS::FITS() { } // just a dummy function to prevent instantiation
00331 inline Bool FITS::isa_digit(char c) { return isdigit(c) ? True : False; }
00332 inline int FITS::digit2bin(char c) { return c - '0'; }
00333 inline Bool FITS::isa_text(char c) { return isprint(c) ? True : False; }
00334 inline Bool FITS::isa_letter(char c) { return isupper(c) ? True : False; }
00335 inline int FITS::letter2bin(char c) { return c - 'A'; }
00336 
00337 ostream & operator << (ostream &, const FITS::ValueType &);
00338 
00339 inline double FITS::tenD(Int numb, int pow) {
00340         return (pow > 0) ? (((double)numb) * tenpowerD[pow]) :
00341             ((pow < 0) ? (((double)numb) / tenpowerD[-pow]) : ((double)numb));
00342 }
00343 inline float FITS::tenF(Int numb, int pow) {
00344         return (pow > 0) ? (((float)numb) * tenpowerF[pow]) :
00345             ((pow < 0) ? (((float)numb) / tenpowerF[-pow]) : ((float)numb));
00346 }
00347 
00348 //<summary> reserved FITS keyword </summary>
00349 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00350 // </reviewed>
00351 
00352 class ReservedFitsKeyword {
00353     public:
00354         const char *aname() const;
00355         FITS::ReservedName name() const;
00356         int namesize() const;
00357         FITS::ValueType type() const;
00358         Bool isindexed() const;
00359         Bool isessential() const;
00360 # if defined(TURBOCPP)
00361         // It is best for the following to be private, but 
00362         // C-Front won't allow an initializer list if they are private.
00363         // This issue isn't that crucial since functions in 
00364         // ReservedFitsKeywordCollection always return const items.
00365     private:
00366 # endif
00367         FITS::ReservedName name_;
00368         const char *aname_;
00369         int namesize_;
00370         FITS::ValueType type_;
00371         Bool isindexed_; // 0 = NOT INDEXED, 1 = INDEXED
00372         Bool isessential_; // 0 = NO, 1 = YES
00373 };
00374 
00375 inline const char *ReservedFitsKeyword::aname() const { return aname_; }
00376 inline int ReservedFitsKeyword::namesize() const { return namesize_; }
00377 inline FITS::ValueType ReservedFitsKeyword::type() const { return type_; }
00378 inline Bool ReservedFitsKeyword::isindexed() const { return isindexed_; }
00379 inline Bool ReservedFitsKeyword::isessential() const { 
00380         return isessential_; }
00381 
00382 //<summary> collection of reserved FITS keywords </summary>
00383 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00384 // </reviewed>
00385 
00386 class ReservedFitsKeywordCollection {
00387     public:
00388         const ReservedFitsKeyword & operator [] (int i) const;
00389         int no() const;
00390         const ReservedFitsKeyword &get(FITS::ReservedName, Bool, FITS::ValueType,
00391                 const void *, int, const char *&) const;
00392         const ReservedFitsKeyword &get(const char *, int, Bool, FITS::ValueType,
00393                 const void *, int, const char *&) const;
00394         const char *aname(FITS::ReservedName) const;
00395         int essential_name(const char *, int) const;
00396         const ReservedFitsKeyword &get_essential(int, Bool, FITS::ValueType,
00397                 const void *, int, const char *&) const;
00398         int isreserved(const char *, int) const;
00399         Bool isunique(int) const;
00400         Bool requires_value(int) const;
00401         const ReservedFitsKeyword &userdef_item() const;
00402         const ReservedFitsKeyword &err_item() const;
00403         const ReservedFitsKeyword &end_item() const;
00404         const ReservedFitsKeyword &spaces() const;
00405         const ReservedFitsKeyword &comment() const;
00406         const ReservedFitsKeyword &history() const;
00407         int rules(const ReservedFitsKeyword &, const char *, int, Bool,
00408                 FITS::ValueType, const void *, int, const char *&) const;
00409     private:
00410         static const int no_items; // number of entries in the table
00411         static const ReservedFitsKeyword &user_def_item; // user-defined keyword
00412         static const ReservedFitsKeyword &error_item; // error in keyword
00413         static const ReservedFitsKeyword &end__item;
00414         static const ReservedFitsKeyword &spaces_item;
00415         static const ReservedFitsKeyword &comment_item;
00416         static const ReservedFitsKeyword &history_item;
00417         static const ReservedFitsKeyword resword[]; // table of reserved words
00418         static const int resalpha[26]; // alphabetic index to table
00419         const ReservedFitsKeyword &match(int, const char *, int, Bool,
00420                 FITS::ValueType, const void *, int, const char *&) const;
00421 
00422 };
00423 
00424 inline const ReservedFitsKeyword & ReservedFitsKeywordCollection::
00425 	operator [] (int i) const { return resword[i]; }
00426 inline int ReservedFitsKeywordCollection::no() const { return no_items; }
00427 inline Bool ReservedFitsKeywordCollection::isunique(int i) const {
00428         return (Bool)(resword[i + 1].name() != resword[i].name()); }
00429 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::userdef_item()
00430         const { return user_def_item; }
00431 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::err_item() 
00432         const { return error_item; }
00433 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::end_item()
00434         const { return end__item; }
00435 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::spaces()
00436         const { return spaces_item; }
00437 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::comment()
00438         const { return comment_item; }
00439 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::history()
00440         const { return history_item; }
00441 
00442 //<summary> analyse the name of a header card </summary>
00443 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00444 // </reviewed>
00445 //<synopsis>
00446 // Analyse the name of a header card
00447 //</synopsis>
00448 
00449 class FitsNameResult {
00450     public:
00451         Bool isaname;   // 1 if there is a name present, otherwise 0
00452         int begpos;     // beginning position of name
00453         int endpos;     // ending position of name
00454         Bool isaindex;  // whether an index is present or not
00455         int index;      // index if present
00456         int len;        // length of name without index
00457         enum ErrMsg { OK = 0, NO_0_NDX };
00458         ErrMsg err;
00459 };
00460 
00461 //<summary> analyse the value of a header card </summary>
00462 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00463 // </reviewed>
00464 //<synopsis>
00465 // Analyse the value of a header card
00466 //</synopsis>
00467 
00468 class FitsValueResult {
00469     public:
00470         FITS::ValueType type;
00471         union {
00472             Bool b;
00473             int s[2];   // for strings, s[0] is offset, s[1] length
00474             Int l;
00475             float f;
00476             double d;
00477         };
00478         Complex c;
00479         IComplex lc;
00480         DComplex dc;
00481         int begpos;             // beginning position of value
00482         int endpos;             // ending position of value
00483         Bool isa_point;         // 1 if a point, otherwise 0
00484         int pointpos;           // position of point, if any
00485         int no_sig;             // number of significant digits
00486         const char *errmsg;     // error message, if any
00487 };
00488 
00489 //<summary> parse a header card </summary>
00490 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00491 // </reviewed>
00492 //<synopsis> 
00493 //  parse a header card 
00494 //</synopsis>
00495 
00496 class FitsParse {
00497         friend class FitsKeywordList;
00498     public:
00499         FitsKeyword &parse(const char *, int); // Parsing one string
00500         int no_errs() const;
00501         const char *err(int) const;
00502     private:
00503         FitsParse(int = 10);
00504         ~FitsParse();
00505         int no_errs_;
00506         const int max_errs;
00507         const char **err_;
00508         int seterr(const char *);
00509         FitsKeyword &mkerr(const char *s, int len);
00510 };
00511 
00512 inline FitsParse::~FitsParse() { delete [] err_; }
00513 inline int FitsParse::no_errs() const { return no_errs_; }
00514 inline const char *FitsParse::err(int i) const { return err_[i]; }
00515 inline int FitsParse::seterr(const char *s) {
00516         return no_errs_ < max_errs ? ( err_[no_errs_++] = s, 0) : -1; }
00517 
00518 //<summary> FITS keyword </summary>
00519 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00520 // </reviewed>
00521 //<synopsis>
00522 // A FITS keyword contains a name, a value and a comment.
00523 //</synopsis>
00524 class FitsKeyword {
00525         friend class FitsKeywordList;
00526         friend class FitsParse;
00527         // A word about friends:  FitsKeywordList accesses the next and prev
00528         // pointers and the FitsKeyword constructors. 
00529         // FitsParse only accesses the FitsKeyword constructors.
00530 
00531     public:
00532 
00533         FitsKeyword(const FitsKeyword &);
00534         FitsKeyword & operator = (const FitsKeyword &);
00535         ~FitsKeyword();
00536 
00537         //<group>
00538         // get info about the name
00539         const char *name() const;
00540         int namelen() const;
00541         Bool isreserved() const;
00542         Bool isindexed() const;
00543         const ReservedFitsKeyword &kw() const;
00544         int index() const;
00545         //</group>
00546 
00547         //<group>
00548         // access the keyword comment
00549         const char *comm() const;
00550         int commlen() const;
00551         //</group>
00552 
00553         // access the error status
00554         int err() const;
00555 
00556         // the datatype of the keyword
00557         FITS::ValueType type() const;
00558 
00559         // access the value of the keyword
00560         //<group>
00561         Bool asBool() const;
00562         const char *asString() const;
00563         int valStrlen() const;
00564         Int asInt() const;
00565         float asFloat() const;
00566         double asDouble() const;
00567         IComplex asIComplex() const;
00568         Complex asComplex() const;
00569         DComplex asDComplex() const;
00570         const void *value() const;
00571         //</group>
00572 
00573         // change the value of the keyword
00574         //<group>
00575         FitsKeyword & operator = (Bool);
00576         FitsKeyword & operator = (const char *);
00577         FitsKeyword & operator = (Int);
00578         FitsKeyword & operator = (float);
00579         FitsKeyword & operator = (double);
00580         FitsKeyword & operator = (IComplex);
00581         FitsKeyword & operator = (Complex);
00582         FitsKeyword & operator = (DComplex);
00583         //</group>
00584 
00585         // change the comment of the keyword
00586         void comm(const char *);
00587 
00588         // change the name of the keyword
00589         void name(const char *);
00590 
00591     private:
00592         FitsKeyword *next_;
00593         FitsKeyword *prev_;
00594 
00595         //<group>
00596         // the keyword name
00597         // if name_ is 0, keyword is not a user defined name
00598         // if ndx is 0, there is no index
00599         char *name_;
00600         const ReservedFitsKeyword *kw_;
00601         int ndx;
00602         short namelen_;
00603         //</group>
00604 
00605         //<group>
00606         // the keyword comment
00607         // if comm_ is 0, there is no comment
00608         char *comm_;
00609         short commlen_;
00610         //</group>
00611 
00612 
00613         //<group>
00614         // the keyword value
00615         FITS::ValueType type_;
00616         union {
00617             Bool bval;
00618             Int ival;
00619             float fval;
00620             double dval;
00621         };
00622         void *val; // pointer to allocated value, if any
00623         short vallen; // only used for string data
00624         void del_val(); // does an appropriate delete based on type
00625         //</group>
00626 
00627         void init(const FitsKeyword &);
00628         void setval(const FITS::ValueType &, const void *, int);
00629         void setcomm(const char *, int);
00630         static void err(const char *, const FITS::ValueType &, const void *,
00631                  const char *);
00632         static void memchk(void *);
00633 
00634         //<group>
00635         // private constructors for use by friends
00636 
00637         // constructs user-defined keywords
00638         // parms: name, namelen, type, val, vallen, comm, commlen
00639         FitsKeyword(const char *, int , 
00640                 FITS::ValueType, const void *, int, const char *, int);
00641         // constructs reserved keywords
00642         // parms: resword, index, val, vallen, comm, commlen
00643         FitsKeyword(const ReservedFitsKeyword *, int,
00644                 FITS::ValueType, const void *, int, const char *, int);
00645         //</group>
00646 
00647 
00648 };
00649 
00650 ostream & operator << (ostream &, const FitsKeyword &);
00651 
00652 inline FitsKeyword::FitsKeyword(const FitsKeyword &k) : next_(0), prev_(0),
00653         name_(0), kw_(0), comm_(0), val(0)  { init(k); }
00654 inline FitsKeyword & FitsKeyword::operator = (const FitsKeyword &k) { 
00655         delete [] name_; delete [] comm_; del_val(); init(k); return *this; }
00656 inline FitsKeyword::~FitsKeyword() { 
00657         delete [] name_; 
00658         delete [] comm_; 
00659         del_val(); 
00660 }
00661 
00662 inline const ReservedFitsKeyword &FitsKeyword::kw() const { return *kw_; }
00663 inline Bool FitsKeyword::isreserved() const { return 
00664         (kw().name() != FITS::ERRWORD && kw().name() != FITS::USER_DEF)
00665                  ? True : False; }
00666 inline const char *FitsKeyword::name() const {
00667         return isreserved() ? kw().aname() : (namelen_ ? name_ : ""); }
00668 inline int FitsKeyword::namelen() const { return namelen_; }
00669 inline Bool FitsKeyword::isindexed() const {return ndx > 0 ? True : False;}
00670 inline int FitsKeyword::index() const { return ndx; }
00671 
00672 inline const char *FitsKeyword::comm() const {
00673     return comm_ ? comm_  : ""; }
00674 inline int FitsKeyword::commlen() const { return commlen_; }
00675 inline int FitsKeyword::err() const { return (kw().name() == FITS::ERRWORD); }
00676 inline FITS::ValueType FitsKeyword::type() const { return type_; }
00677 
00678 inline Bool FitsKeyword::asBool() const { return bval; }
00679 inline const char *FitsKeyword::asString() const {
00680         return vallen ? (const char *)val : ""; }
00681 inline int FitsKeyword::valStrlen() const { return vallen; }
00682 inline Int FitsKeyword::asInt() const { 
00683         if( type() != FITS::LONG ) {
00684                 cerr << "Unexpected keyword type in FitsKeyword::asInt()\n";
00685                 exit(1);
00686         }
00687         return ival;
00688 }
00689 inline float FitsKeyword::asFloat() const { 
00690         switch( type() ) { 
00691                 case FITS::BYTE:
00692                 case FITS::SHORT:
00693                 case FITS::LONG: return (float)ival;
00694                 case FITS::FLOAT: return fval;
00695                 case FITS::DOUBLE: return (float)dval;
00696                 default:
00697                         cerr << "Unexpected keyword type in asFloat()\n";
00698                         exit(1);
00699         }
00700         return 0.0;
00701 }
00702 inline double FitsKeyword::asDouble() const { 
00703         switch( type() ) { 
00704                 case FITS::BYTE:
00705                 case FITS::SHORT:
00706                 case FITS::LONG: return (double)ival;
00707                 case FITS::FLOAT: return (double)fval;
00708                 case FITS::DOUBLE: return dval;
00709                 default:
00710                         cerr << "Unexpected keyword type in asDouble()\n";
00711                         exit(1);
00712         }
00713         return 0.0;
00714 }
00715 inline IComplex FitsKeyword::asIComplex() const {
00716         return *((IComplex *)val); }
00717 inline Complex FitsKeyword::asComplex() const {
00718         return *((Complex *)val); }
00719 inline DComplex FitsKeyword::asDComplex() const {
00720         return *((DComplex *)val); }
00721 
00722 inline FitsKeyword & FitsKeyword::operator = (Bool x) {
00723         bval = x; type_ = FITS::LOGICAL; return *this; }
00724 inline FitsKeyword & FitsKeyword::operator = (Int x) {
00725         ival = x; type_ = FITS::LONG; return *this; }
00726 inline FitsKeyword & FitsKeyword::operator = (float x) {
00727         fval = x; type_ = FITS::FLOAT; return *this; }
00728 inline FitsKeyword & FitsKeyword::operator = (double x) {
00729         dval = x; type_ = FITS::DOUBLE; return *this; }
00730 inline FitsKeyword & FitsKeyword::operator = (IComplex x) {
00731         *((IComplex *)val) = x; type_ = FITS::ICOMPLEX; return *this; }
00732 inline FitsKeyword & FitsKeyword::operator = (Complex x) {
00733         *((Complex *)val) = x; type_ = FITS::COMPLEX; return *this; }
00734 inline FitsKeyword & FitsKeyword::operator = (DComplex x) {
00735         *((DComplex *)val) = x; type_ = FITS::DCOMPLEX; return *this; }
00736 
00737 class ConstFitsKeywordList; // forward declaration
00738 
00739 //<summary> linked list of FITS keywords </summary>
00740 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00741 // </reviewed>
00742 //<synopsis>
00743 // A linked list of FITS keywords.
00744 //</synopsis>
00745 
00746 class FitsKeywordList {
00747     public:
00748         FitsKeywordList();
00749         ~FitsKeywordList();
00750         FitsKeywordList(const FitsKeywordList &);
00751         FitsKeywordList(ConstFitsKeywordList &);
00752         FitsKeywordList & operator = (const FitsKeywordList &);
00753 
00754         // Convert the list to a string containing the 80-byte FITS headers.
00755         std::string toString() const;
00756 
00757         // delete the current keyword (the thing returned by curr()) from the list
00758         void del();
00759 
00760         // Add (make) a reserved keyword with the given value and optional comment
00761         // The comment will be truncated if necessary to fit the available space.
00762         // String values must be less than 69 characters.  String values longer than
00763         // that will result in an ERROR keyword instead of the desired keyword.
00764         // <group>
00765         void mk(FITS::ReservedName k, Bool v, const char *c = 0);
00766         void mk(FITS::ReservedName k, const char *v = 0, const char *c = 0);
00767         void mk(FITS::ReservedName k, Int v, const char *c = 0);
00768         void mk(FITS::ReservedName k, long v, const char *c = 0);
00769         void mk(FITS::ReservedName k, double v, const char *c = 0);
00770         // </group>
00771 
00772         // Add (make) an indexed reserved keyword with the given value and optional comment
00773         // The comment will be truncated if necessary to fit the available space.
00774         // String values must be less than 69 characters.  String values longer than
00775         // that will result in an ERROR keyword instead of the desired keyword.
00776         // <group>
00777         void mk(int n, FITS::ReservedName k, Bool v, const char *c = 0);
00778         void mk(int n, FITS::ReservedName k, const char *v, const char *c = 0);
00779         void mk(int n, FITS::ReservedName k, Int v, const char *c = 0);
00780         void mk(int n, FITS::ReservedName k, long v, const char *c = 0);
00781         void mk(int n, FITS::ReservedName k, double v, const char *c = 0);
00782         // </group>
00783 
00784         // Add (make) a user defined keyword with the given name, value and optional comment.
00785         // The comment will be truncated if necessary to fit the available space.
00786         // The name must be no longer than 8 characters.  Names longer than that will 
00787         // result in an ERROR keyword instead of the desired keyword.
00788         // String values must no longer than 69 characters.  String values longer than
00789         // that will result in an ERROR keyword instead of the desired keyword.
00790         // <group>
00791         void mk(const char *n, Bool v, const char *c = 0);
00792         void mk(const char *n, const char *v = 0, const char *c = 0);
00793         void mk(const char *n, Int v, const char *c = 0);
00794         void mk(const char *n, long v, const char *c = 0);
00795         void mk(const char *n, float v, const char *c = 0);
00796         void mk(const char *n, double v, const char *c = 0);
00797         void mk(const char *n, Int r, Int i, const char *c = 0);
00798         void mk(const char *n, float r, float i, const char *c = 0);
00799         void mk(const char *n, double r, double i, const char *c = 0);
00800         // </group>
00801 
00802         // add a spaces line
00803         void spaces(const char *n = 0, const char *c = 0);
00804 
00805         // add a comment card
00806         void comment(const char *n = 0, const char *c = 0);
00807 
00808         // add a history card
00809         void history(const char *c = 0);
00810 
00811         // add the end card.  This must be at the end of the list.
00812         void end();
00813         
00814         // Retrieve specific keywords -- these also set the current mark
00815         //<group>
00816         // return the i-th keyword -- keyword numbering starts with 0
00817         FitsKeyword * operator () (int);
00818         // return first and next non-indexed reserved keyword
00819         FitsKeyword * operator () (const FITS::ReservedName &);
00820         FitsKeyword * next(const FITS::ReservedName &);
00821         // return first and next indexed reserved keyword
00822         FitsKeyword * operator () (const FITS::ReservedName &, int);
00823         FitsKeyword * next(const FITS::ReservedName &, int);
00824         // return first and next user-defined keyword
00825         FitsKeyword * operator () (const char *);
00826         FitsKeyword * next(const char *);
00827         //</group>
00828 
00829         //<group>
00830         Bool isempty() const;
00831         void     first();
00832         void     last();
00833         FitsKeyword *next();
00834         FitsKeyword *prev();
00835         FitsKeyword *curr();
00836         //</group>
00837 
00838         //<group>
00839         void delete_all(); 
00840         int rules(FitsKeyword &, 
00841                   FITSErrorHandler errhandler = FITSError::defaultHandler);
00842         int rules(FITSErrorHandler errhandler = FITSError::defaultHandler);
00843         Bool basic_rules();
00844         //</group>
00845 
00846         //<group>
00847         // For parsing a single string
00848         void parse(const char *, int); 
00849         int no_parse_errs() const;
00850         const char *parse_err(int) const;
00851         //</group>
00852 
00853         void insert(FitsKeyword &);
00854     private:
00855         FitsKeyword *beg_;
00856         FitsKeyword *end_;
00857         FitsKeyword *pos;
00858         int total;
00859         int cursor;
00860         FitsKeyword &make(const char *nm,
00861                 FITS::ValueType t, const void *v, const char *c);
00862         FitsKeyword &make(FITS::ReservedName nm,
00863                 FITS::ValueType t, const void *v, const char *c);
00864         FitsKeyword &make(int ind, FITS::ReservedName nm,
00865                 FITS::ValueType t, const void *v, const char *c);
00866         // construct an error keyword - this happens when a name is invalid (NULL
00867         // or more than 8 characters) or a string value is too long (more than
00868         // 69 characters).  It is the responsibility of the caller to the 
00869         // several mk functions to ensure that that doesn't happen.  By the time
00870         // it gets here, it is assumed that such problems are true errors.
00871         // This is used by the private make functions.
00872         FitsKeyword &makeErrKeyword(const char *name, FITS::ValueType type, 
00873                                     const void *val, const char *errmsg);
00874         FitsParse card;
00875 };
00876 
00877 ostream & operator << (ostream &o, FitsKeywordList &); // print the entire list
00878 
00879 inline FitsKeywordList::FitsKeywordList() : beg_(0), end_(0), pos(0), 
00880         total(0), cursor(0) { }
00881 inline FitsKeywordList::~FitsKeywordList() { delete_all(); }
00882 inline Bool FitsKeywordList::isempty() const { return total == 0 ? True : False; }
00883 inline void FitsKeywordList::first() { cursor = 0; pos = beg_; }
00884 inline void FitsKeywordList::last() { cursor = total; pos = end_; }
00885 inline FitsKeyword *FitsKeywordList::curr() { return pos; }
00886 inline FitsKeyword *FitsKeywordList::operator () (const FITS::ReservedName &n) {
00887         first(); return next(n); }
00888 inline FitsKeyword *FitsKeywordList::operator () (const FITS::ReservedName &n,
00889         int ndx) { first(); return next(n,ndx); }
00890 inline FitsKeyword *FitsKeywordList::operator () (const char *w) {
00891         first(); return next(w); }
00892 inline void FitsKeywordList::parse(const char *s, int l) {
00893         insert(card.parse(s,l)); }
00894 inline int FitsKeywordList::no_parse_errs() const { return card.no_errs();}
00895 inline const char *FitsKeywordList::parse_err(int n) const { 
00896         return card.err(n); }
00897 
00898 // FitsKeyword constructors for non-indexed Reserved keywords
00899 inline void FitsKeywordList::mk(FITS::ReservedName k, Bool v, const char *c) {
00900         insert(make(k,FITS::LOGICAL,&v,c)); }
00901 inline void FitsKeywordList::mk(FITS::ReservedName k, const char *v, 
00902         const char *c) { insert(make(k,FITS::STRING,v,c)); }
00903 inline void FitsKeywordList::mk(FITS::ReservedName k, Int v, const char *c) {
00904         insert(make(k,FITS::LONG,&v,c)); }
00905 inline void FitsKeywordList::mk(FITS::ReservedName k, long v, const char *c) {
00906         insert(make(k,FITS::LONG,&v,c)); }
00907 inline void FitsKeywordList::mk(FITS::ReservedName k, double v, const char *c) {
00908         insert(make(k,FITS::DOUBLE,&v,c)); }
00909 // FitsKeyword constructors for indexed Reserved keywords
00910 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, Bool v, 
00911         const char *c) { 
00912         Bool tmp; tmp = v; insert(make(n,k,FITS::LOGICAL,&tmp,c)); }
00913 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, const char *v, 
00914         const char *c) { insert(make(n,k,FITS::STRING,v,c)); }
00915 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, Int v, 
00916         const char *c) { insert(make(n,k,FITS::LONG,&v,c)); }
00917 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, long v, 
00918         const char *c) { insert(make(n,k,FITS::LONG,&v,c)); }
00919 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, double v, 
00920         const char *c) { insert(make(n,k,FITS::DOUBLE,&v,c)); }
00921 // FitsKeyword constructors for User-Defined keywords
00922 inline void FitsKeywordList::mk(const char *n, Bool v, const char *c) {
00923         Bool tmp; tmp = v; insert(make(n,FITS::LOGICAL,&tmp,c)); }
00924 inline void FitsKeywordList::mk(const char *n, const char *v, const char *c) {
00925         insert(make(n,FITS::STRING,v,c)); }
00926 inline void FitsKeywordList::mk(const char *n, Int v, const char *c) {
00927         insert(make(n,FITS::LONG,&v,c)); }
00928 inline void FitsKeywordList::mk(const char *n, long v, const char *c) {
00929         insert(make(n,FITS::LONG,&v,c)); }
00930 inline void FitsKeywordList::mk(const char *n, float v, const char *c) {
00931         insert(make(n,FITS::FLOAT,&v,c)); }
00932 inline void FitsKeywordList::mk(const char *n, double v, const char *c) {
00933         insert(make(n,FITS::DOUBLE,&v,c)); }
00934 inline void FitsKeywordList::mk(const char *n, Int r, Int i, const char *c) {
00935         IComplex v(r,i);
00936         insert(make(n,FITS::ICOMPLEX,&v,c)); }
00937 inline void FitsKeywordList::mk(const char *n, float r, float i, const char *c)
00938         { Complex v(r,i); insert(make(n,FITS::COMPLEX,&v,c)); }
00939 inline void FitsKeywordList::mk(const char *n, double r, double i, 
00940         const char *c) { DComplex v(r,i);
00941         insert(make(n,FITS::DCOMPLEX,&v,c)); }
00942 // Additional keyword constructors for commentary, etc.
00943 inline void FitsKeywordList::spaces(const char *n, const char *c) {
00944         insert((n == 0 ? make(FITS::SPACES,FITS::NOVALUE,0,c) :
00945                (c == 0 ? make(FITS::SPACES,FITS::NOVALUE,0,n) : 
00946                           make(n,FITS::NOVALUE,0,c)))); }
00947 inline void FitsKeywordList::comment(const char *n, const char *c) {
00948         insert((n == 0 ? make(FITS::COMMENT,FITS::NOVALUE,0,c) :
00949                (c == 0 ? make(FITS::COMMENT,FITS::NOVALUE,0,n) :
00950                           make(n,FITS::NOVALUE,0,c)))); }
00951 inline void FitsKeywordList::history(const char *c) {
00952         insert(make(FITS::HISTORY,FITS::NOVALUE,0,c)); }
00953 inline void FitsKeywordList::end() {
00954         insert(make(FITS::END,FITS::NOVALUE,0,0)); }
00955 
00956 //<summary> list of read-only FITS keywords </summary>
00957 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00958 // </reviewed>
00959 
00960 class ConstFitsKeywordList {
00961     public:
00962         ConstFitsKeywordList(FitsKeywordList &x) : kw(x) { }
00963 
00964         const FitsKeyword * operator () (int n) { return kw(n); }
00965         const FitsKeyword * operator () (const FITS::ReservedName &x) {
00966                 return kw(x); }
00967         const FitsKeyword * next(const FITS::ReservedName &x) {
00968                 return kw.next(x); }
00969         const FitsKeyword * operator () (const FITS::ReservedName &x, int n) {
00970                 return kw(x,n); }
00971         const FitsKeyword * next(const FITS::ReservedName &x, int n) {
00972                 return kw.next(x,n); }
00973         const FitsKeyword * operator () (const char *x) { return kw(x); }
00974         const FitsKeyword * next(const char *x) { return kw.next(x); }
00975 
00976         Bool isempty() const            { return kw.isempty(); }
00977         void     first()                { kw.first(); }
00978         void     last()                 { kw.last(); }
00979         const FitsKeyword *next()       { return kw.next(); }
00980         const FitsKeyword *prev()       { return kw.prev(); }
00981         const FitsKeyword *curr()       { return kw.curr(); }
00982 
00983     private:
00984         FitsKeywordList &kw;
00985 };
00986 
00987 //<summary> translator between Keyword lists and fixed FITS cars </summary>
00988 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00989 // </reviewed>
00990 //<synopsis> 
00991 // also contains the parser ???
00992 //</synopsis> 
00993 
00994 class FitsKeyCardTranslator {
00995     public:
00996         FitsKeyCardTranslator(int = 100);
00997         ~FitsKeyCardTranslator();
00998         FitsKeywordList & parse(const char *, 
00999                 FitsKeywordList &, int, FITSErrorHandler, Bool);
01000         int build(char *, FitsKeywordList &);
01001         int no_errs() const;
01002         const char *err(int) const;
01003         int err_cardno(int) const;
01004         static void fmtcard(char *, const FitsKeyword &);
01005     private:
01006         int cardno;             // the current card number within record
01007         const int FitsCardSize;
01008         const int FitsMaxCard;
01009         const int FitsRecSize;
01010         int max_errs;
01011         int no_errs_;
01012         const char **err_;
01013         int *err_cardno_;
01014         char *blanks;
01015 };
01016 
01017 inline FitsKeyCardTranslator::~FitsKeyCardTranslator() {
01018         delete [] err_; delete [] err_cardno_; delete [] blanks; }
01019 inline int FitsKeyCardTranslator::no_errs() const { return no_errs_; }
01020 inline const char *FitsKeyCardTranslator::err(int i) const { return err_[i]; }
01021 inline int FitsKeyCardTranslator::err_cardno(int i) const {
01022         return err_cardno_[i]; }
01023 
01024 // <summary>Utility functions for floating point values</summary>
01025 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
01026 // </reviewed>
01027 class FitsFPUtil
01028 {
01029 public:
01030     // These functions are useful to tell if some type is a floating point type.
01031     // This is useful in a templated function, where the processing can vary
01032     // depending on whether the type is FP or not (e.g. blank handling).
01033     // <group>
01034     static Bool isFP(const float *);
01035     static Bool isFP(const double *);
01036     static Bool isFP(const void *);
01037     // </group>
01038 
01039     // For blanking purposes, we need to be able to get a NaN. The NaN we set
01040     // is all bits on.
01041     // <group>
01042     static void setNaN(double &val);
01043     static void setNaN(float &val);
01044     // </group>
01045 };
01046 
01047 
01048 } //# NAMESPACE CASACORE - END
01049 
01050 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1