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

Generated on Mon Sep 1 22:34:31 2008 for NRAOCASA by  doxygen 1.5.1