casa
$Rev:20696$
|
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: fits.h 20493 2009-01-16 10:51:43Z gervandiepen $ 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 ALTRPIX, DATE_MAP 00257 }; 00258 00259 // Types of FITS Records 00260 enum FitsRecType { 00261 InitialState, BadBeginningRecord, HDURecord, 00262 UnrecognizableRecord, SpecialRecord, EndOfFile 00263 }; 00264 00265 // Supported FITS Physical Devices 00266 enum FitsDevice { 00267 Disk, Std, Tape9 00268 }; 00269 00270 // Types of FITS Header-Data Units 00271 enum HDUType { 00272 NotAHDU, PrimaryArrayHDU, PrimaryGroupHDU, AsciiTableHDU, 00273 BinaryTableHDU, ImageExtensionHDU, UnknownExtensionHDU, 00274 PrimaryTableHDU 00275 }; 00276 00277 // Options on FITS array manipulations 00278 enum FitsArrayOption { NoOpt = 0, CtoF = 1, FtoC = 2}; 00279 00280 static ReservedFitsKeywordCollection &ResWord; 00281 static void valstr(ostream &o, const ValueType &ty, const void *val); 00282 static Bool isa_digit(char c); 00283 static int digit2bin(char c); 00284 static Bool isa_text(char c); 00285 static Bool isa_letter(char); 00286 static int letter2bin(char); 00287 static void fstr2str(char *, const char *, int); 00288 static int str2fstr(char *, const char *, int); 00289 static void get_name(const char *s, int len, FitsNameResult &result); 00290 static int get_value_id(const char *s, int l, int &pos); 00291 static void get_value(const char *s, int len, FitsValueResult &result); 00292 static int trim_comment(const char *s, int len); 00293 static int chk_comment(const char *s, int len); 00294 static int get_comment(const char *s, int len, int &begpos); 00295 static void get_numeric(const char *s, int len, FitsValueResult &result); 00296 // utility function to parse the binary table variable array 00297 // column (i.e. uses the heap) of the form nPt(dddd) where n 00298 // is either 0 or 1, t is one of the standard FITS binary table 00299 // column types and dddd is the maximum number of elements used 00300 // by this column. If there is a format error in the input 00301 // string (*s), then valType will have the value NOVALUE and 00302 // maxelem will be -1. 00303 static void parse_vatform(const char *s, FITS::ValueType &valType, 00304 int &maxelem); 00305 static const Int minInt; 00306 static const Int maxInt; 00307 static const float minfloat; 00308 static const float maxfloat; 00309 static const double mindouble; 00310 static const double maxdouble; 00311 00312 private: 00313 FITS(); 00314 static double tenpowerD[309]; 00315 static float tenpowerF[39]; 00316 static const int minfltexp; 00317 static const int maxfltexp; 00318 static const int mindblexp; 00319 static const int maxdblexp; 00320 static const int maxsigdigits; 00321 static const int maxdigl; // max digits in a long 00322 static const int maxexpdig; // max digits in an exponent 00323 static double tenD(Int, int); 00324 static float tenF(Int, int); 00325 static int ckaccum(double &, Int, int); 00326 static int ckaccum(float &, Int, int); 00327 }; 00328 00329 inline FITS::FITS() { } // just a dummy function to prevent instantiation 00330 inline Bool FITS::isa_digit(char c) { return isdigit(c) ? True : False; } 00331 inline int FITS::digit2bin(char c) { return c - '0'; } 00332 inline Bool FITS::isa_text(char c) { return isprint(c) ? True : False; } 00333 inline Bool FITS::isa_letter(char c) { return isupper(c) ? True : False; } 00334 inline int FITS::letter2bin(char c) { return c - 'A'; } 00335 00336 ostream & operator << (ostream &, const FITS::ValueType &); 00337 00338 inline double FITS::tenD(Int numb, int pow) { 00339 return (pow > 0) ? (((double)numb) * tenpowerD[pow]) : 00340 ((pow < 0) ? (((double)numb) / tenpowerD[-pow]) : ((double)numb)); 00341 } 00342 inline float FITS::tenF(Int numb, int pow) { 00343 return (pow > 0) ? (((float)numb) * tenpowerF[pow]) : 00344 ((pow < 0) ? (((float)numb) / tenpowerF[-pow]) : ((float)numb)); 00345 } 00346 00347 //<summary> reserved FITS keyword </summary> 00348 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00349 // </reviewed> 00350 00351 class ReservedFitsKeyword { 00352 public: 00353 const char *aname() const; 00354 FITS::ReservedName name() const; 00355 int namesize() const; 00356 FITS::ValueType type() const; 00357 Bool isindexed() const; 00358 Bool isessential() const; 00359 # if defined(TURBOCPP) 00360 // It is best for the following to be private, but 00361 // C-Front won't allow an initializer list if they are private. 00362 // This issue isn't that crucial since functions in 00363 // ReservedFitsKeywordCollection always return const items. 00364 private: 00365 # endif 00366 FITS::ReservedName name_; 00367 const char *aname_; 00368 int namesize_; 00369 FITS::ValueType type_; 00370 Bool isindexed_; // 0 = NOT INDEXED, 1 = INDEXED 00371 Bool isessential_; // 0 = NO, 1 = YES 00372 }; 00373 00374 inline const char *ReservedFitsKeyword::aname() const { return aname_; } 00375 inline int ReservedFitsKeyword::namesize() const { return namesize_; } 00376 inline FITS::ValueType ReservedFitsKeyword::type() const { return type_; } 00377 inline Bool ReservedFitsKeyword::isindexed() const { return isindexed_; } 00378 inline Bool ReservedFitsKeyword::isessential() const { 00379 return isessential_; } 00380 00381 //<summary> collection of reserved FITS keywords </summary> 00382 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00383 // </reviewed> 00384 00385 class ReservedFitsKeywordCollection { 00386 public: 00387 const ReservedFitsKeyword & operator [] (int i) const; 00388 int no() const; 00389 const ReservedFitsKeyword &get(FITS::ReservedName, Bool, FITS::ValueType, 00390 const void *, int, const char *&) const; 00391 const ReservedFitsKeyword &get(const char *, int, Bool, FITS::ValueType, 00392 const void *, int, const char *&) const; 00393 const char *aname(FITS::ReservedName) const; 00394 int essential_name(const char *, int) const; 00395 const ReservedFitsKeyword &get_essential(int, Bool, FITS::ValueType, 00396 const void *, int, const char *&) const; 00397 int isreserved(const char *, int) const; 00398 Bool isunique(int) const; 00399 Bool requires_value(int) const; 00400 const ReservedFitsKeyword &userdef_item() const; 00401 const ReservedFitsKeyword &err_item() const; 00402 const ReservedFitsKeyword &end_item() const; 00403 const ReservedFitsKeyword &spaces() const; 00404 const ReservedFitsKeyword &comment() const; 00405 const ReservedFitsKeyword &history() const; 00406 int rules(const ReservedFitsKeyword &, const char *, int, Bool, 00407 FITS::ValueType, const void *, int, const char *&) const; 00408 private: 00409 static const int no_items; // number of entries in the table 00410 static const ReservedFitsKeyword &user_def_item; // user-defined keyword 00411 static const ReservedFitsKeyword &error_item; // error in keyword 00412 static const ReservedFitsKeyword &end__item; 00413 static const ReservedFitsKeyword &spaces_item; 00414 static const ReservedFitsKeyword &comment_item; 00415 static const ReservedFitsKeyword &history_item; 00416 static const ReservedFitsKeyword resword[]; // table of reserved words 00417 static const int resalpha[26]; // alphabetic index to table 00418 const ReservedFitsKeyword &match(int, const char *, int, Bool, 00419 FITS::ValueType, const void *, int, const char *&) const; 00420 00421 }; 00422 00423 inline const ReservedFitsKeyword & ReservedFitsKeywordCollection:: 00424 operator [] (int i) const { return resword[i]; } 00425 inline int ReservedFitsKeywordCollection::no() const { return no_items; } 00426 inline Bool ReservedFitsKeywordCollection::isunique(int i) const { 00427 return (Bool)(resword[i + 1].name() != resword[i].name()); } 00428 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::userdef_item() 00429 const { return user_def_item; } 00430 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::err_item() 00431 const { return error_item; } 00432 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::end_item() 00433 const { return end__item; } 00434 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::spaces() 00435 const { return spaces_item; } 00436 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::comment() 00437 const { return comment_item; } 00438 inline const ReservedFitsKeyword &ReservedFitsKeywordCollection::history() 00439 const { return history_item; } 00440 00441 //<summary> analyse the name of a header card </summary> 00442 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00443 // </reviewed> 00444 //<synopsis> 00445 // Analyse the name of a header card 00446 //</synopsis> 00447 00448 class FitsNameResult { 00449 public: 00450 Bool isaname; // 1 if there is a name present, otherwise 0 00451 int begpos; // beginning position of name 00452 int endpos; // ending position of name 00453 Bool isaindex; // whether an index is present or not 00454 int index; // index if present 00455 int len; // length of name without index 00456 enum ErrMsg { OK = 0, NO_0_NDX }; 00457 ErrMsg err; 00458 }; 00459 00460 //<summary> analyse the value of a header card </summary> 00461 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00462 // </reviewed> 00463 //<synopsis> 00464 // Analyse the value of a header card 00465 //</synopsis> 00466 00467 class FitsValueResult { 00468 public: 00469 FITS::ValueType type; 00470 union { 00471 Bool b; 00472 int s[2]; // for strings, s[0] is offset, s[1] length 00473 Int l; 00474 float f; 00475 double d; 00476 }; 00477 Complex c; 00478 IComplex lc; 00479 DComplex dc; 00480 int begpos; // beginning position of value 00481 int endpos; // ending position of value 00482 Bool isa_point; // 1 if a point, otherwise 0 00483 int pointpos; // position of point, if any 00484 int no_sig; // number of significant digits 00485 const char *errmsg; // error message, if any 00486 }; 00487 00488 //<summary> parse a header card </summary> 00489 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00490 // </reviewed> 00491 //<synopsis> 00492 // parse a header card 00493 //</synopsis> 00494 00495 class FitsParse { 00496 friend class FitsKeywordList; 00497 public: 00498 FitsKeyword &parse(const char *, int); // Parsing one string 00499 int no_errs() const; 00500 const char *err(int) const; 00501 private: 00502 FitsParse(int = 10); 00503 ~FitsParse(); 00504 int no_errs_; 00505 const int max_errs; 00506 const char **err_; 00507 int seterr(const char *); 00508 FitsKeyword &mkerr(const char *s, int len); 00509 }; 00510 00511 inline FitsParse::~FitsParse() { delete [] err_; } 00512 inline int FitsParse::no_errs() const { return no_errs_; } 00513 inline const char *FitsParse::err(int i) const { return err_[i]; } 00514 inline int FitsParse::seterr(const char *s) { 00515 return no_errs_ < max_errs ? ( err_[no_errs_++] = s, 0) : -1; } 00516 00517 //<summary> FITS keyword </summary> 00518 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00519 // </reviewed> 00520 //<synopsis> 00521 // A FITS keyword contains a name, a value and a comment. 00522 //</synopsis> 00523 class FitsKeyword { 00524 friend class FitsKeywordList; 00525 friend class FitsParse; 00526 // A word about friends: FitsKeywordList accesses the next and prev 00527 // pointers and the FitsKeyword constructors. 00528 // FitsParse only accesses the FitsKeyword constructors. 00529 00530 public: 00531 00532 FitsKeyword(const FitsKeyword &); 00533 FitsKeyword & operator = (const FitsKeyword &); 00534 ~FitsKeyword(); 00535 00536 //<group> 00537 // get info about the name 00538 const char *name() const; 00539 int namelen() const; 00540 Bool isreserved() const; 00541 Bool isindexed() const; 00542 const ReservedFitsKeyword &kw() const; 00543 int index() const; 00544 //</group> 00545 00546 //<group> 00547 // access the keyword comment 00548 const char *comm() const; 00549 int commlen() const; 00550 //</group> 00551 00552 // access the error status 00553 int err() const; 00554 00555 // the datatype of the keyword 00556 FITS::ValueType type() const; 00557 00558 // access the value of the keyword 00559 //<group> 00560 Bool asBool() const; 00561 const char *asString() const; 00562 int valStrlen() const; 00563 Int asInt() const; 00564 float asFloat() const; 00565 double asDouble() const; 00566 IComplex asIComplex() const; 00567 Complex asComplex() const; 00568 DComplex asDComplex() const; 00569 const void *value() const; 00570 //</group> 00571 00572 // change the value of the keyword 00573 //<group> 00574 FitsKeyword & operator = (Bool); 00575 FitsKeyword & operator = (const char *); 00576 FitsKeyword & operator = (Int); 00577 FitsKeyword & operator = (float); 00578 FitsKeyword & operator = (double); 00579 FitsKeyword & operator = (IComplex); 00580 FitsKeyword & operator = (Complex); 00581 FitsKeyword & operator = (DComplex); 00582 //</group> 00583 00584 // change the comment of the keyword 00585 void comm(const char *); 00586 00587 // change the name of the keyword 00588 void name(const char *); 00589 00590 private: 00591 FitsKeyword *next_; 00592 FitsKeyword *prev_; 00593 00594 //<group> 00595 // the keyword name 00596 // if name_ is 0, keyword is not a user defined name 00597 // if ndx is 0, there is no index 00598 char *name_; 00599 const ReservedFitsKeyword *kw_; 00600 int ndx; 00601 short namelen_; 00602 //</group> 00603 00604 //<group> 00605 // the keyword comment 00606 // if comm_ is 0, there is no comment 00607 char *comm_; 00608 short commlen_; 00609 //</group> 00610 00611 00612 //<group> 00613 // the keyword value 00614 FITS::ValueType type_; 00615 union { 00616 Bool bval; 00617 Int ival; 00618 float fval; 00619 double dval; 00620 }; 00621 void *val; // pointer to allocated value, if any 00622 short vallen; // only used for string data 00623 void del_val(); // does an appropriate delete based on type 00624 //</group> 00625 00626 void init(const FitsKeyword &); 00627 void setval(const FITS::ValueType &, const void *, int); 00628 void setcomm(const char *, int); 00629 static void err(const char *, const FITS::ValueType &, const void *, 00630 const char *); 00631 static void memchk(void *); 00632 00633 //<group> 00634 // private constructors for use by friends 00635 00636 // constructs user-defined keywords 00637 // parms: name, namelen, type, val, vallen, comm, commlen 00638 FitsKeyword(const char *, int , 00639 FITS::ValueType, const void *, int, const char *, int); 00640 // constructs reserved keywords 00641 // parms: resword, index, val, vallen, comm, commlen 00642 FitsKeyword(const ReservedFitsKeyword *, int, 00643 FITS::ValueType, const void *, int, const char *, int); 00644 //</group> 00645 00646 00647 }; 00648 00649 ostream & operator << (ostream &, const FitsKeyword &); 00650 00651 inline FitsKeyword::FitsKeyword(const FitsKeyword &k) : next_(0), prev_(0), 00652 name_(0), kw_(0), comm_(0), val(0) { init(k); } 00653 inline FitsKeyword & FitsKeyword::operator = (const FitsKeyword &k) { 00654 delete [] name_; delete [] comm_; del_val(); init(k); return *this; } 00655 inline FitsKeyword::~FitsKeyword() { 00656 delete [] name_; 00657 delete [] comm_; 00658 del_val(); 00659 } 00660 00661 inline const ReservedFitsKeyword &FitsKeyword::kw() const { return *kw_; } 00662 inline Bool FitsKeyword::isreserved() const { return 00663 (kw().name() != FITS::ERRWORD && kw().name() != FITS::USER_DEF) 00664 ? True : False; } 00665 inline const char *FitsKeyword::name() const { 00666 return isreserved() ? kw().aname() : (namelen_ ? name_ : ""); } 00667 inline int FitsKeyword::namelen() const { return namelen_; } 00668 inline Bool FitsKeyword::isindexed() const {return ndx > 0 ? True : False;} 00669 inline int FitsKeyword::index() const { return ndx; } 00670 00671 inline const char *FitsKeyword::comm() const { 00672 return comm_ ? comm_ : ""; } 00673 inline int FitsKeyword::commlen() const { return commlen_; } 00674 inline int FitsKeyword::err() const { return (kw().name() == FITS::ERRWORD); } 00675 inline FITS::ValueType FitsKeyword::type() const { return type_; } 00676 00677 inline Bool FitsKeyword::asBool() const { return bval; } 00678 inline const char *FitsKeyword::asString() const { 00679 return vallen ? (const char *)val : ""; } 00680 inline int FitsKeyword::valStrlen() const { return vallen; } 00681 inline Int FitsKeyword::asInt() const { 00682 if( type() != FITS::LONG ) { 00683 cerr << "Unexpected keyword type in FitsKeyword::asInt()\n"; 00684 exit(1); 00685 } 00686 return ival; 00687 } 00688 inline float FitsKeyword::asFloat() const { 00689 switch( type() ) { 00690 case FITS::BYTE: 00691 case FITS::SHORT: 00692 case FITS::LONG: return (float)ival; 00693 case FITS::FLOAT: return fval; 00694 case FITS::DOUBLE: return (float)dval; 00695 default: 00696 cerr << "Unexpected keyword type in asFloat()\n"; 00697 exit(1); 00698 } 00699 return 0.0; 00700 } 00701 inline double FitsKeyword::asDouble() const { 00702 switch( type() ) { 00703 case FITS::BYTE: 00704 case FITS::SHORT: 00705 case FITS::LONG: return (double)ival; 00706 case FITS::FLOAT: return (double)fval; 00707 case FITS::DOUBLE: return dval; 00708 default: 00709 cerr << "Unexpected keyword type in asDouble()\n"; 00710 exit(1); 00711 } 00712 return 0.0; 00713 } 00714 inline IComplex FitsKeyword::asIComplex() const { 00715 return *((IComplex *)val); } 00716 inline Complex FitsKeyword::asComplex() const { 00717 return *((Complex *)val); } 00718 inline DComplex FitsKeyword::asDComplex() const { 00719 return *((DComplex *)val); } 00720 00721 inline FitsKeyword & FitsKeyword::operator = (Bool x) { 00722 bval = x; type_ = FITS::LOGICAL; return *this; } 00723 inline FitsKeyword & FitsKeyword::operator = (Int x) { 00724 ival = x; type_ = FITS::LONG; return *this; } 00725 inline FitsKeyword & FitsKeyword::operator = (float x) { 00726 fval = x; type_ = FITS::FLOAT; return *this; } 00727 inline FitsKeyword & FitsKeyword::operator = (double x) { 00728 dval = x; type_ = FITS::DOUBLE; return *this; } 00729 inline FitsKeyword & FitsKeyword::operator = (IComplex x) { 00730 *((IComplex *)val) = x; type_ = FITS::ICOMPLEX; return *this; } 00731 inline FitsKeyword & FitsKeyword::operator = (Complex x) { 00732 *((Complex *)val) = x; type_ = FITS::COMPLEX; return *this; } 00733 inline FitsKeyword & FitsKeyword::operator = (DComplex x) { 00734 *((DComplex *)val) = x; type_ = FITS::DCOMPLEX; return *this; } 00735 00736 class ConstFitsKeywordList; // forward declaration 00737 00738 //<summary> linked list of FITS keywords </summary> 00739 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00740 // </reviewed> 00741 //<synopsis> 00742 // A linked list of FITS keywords. 00743 //</synopsis> 00744 00745 class FitsKeywordList { 00746 public: 00747 FitsKeywordList(); 00748 ~FitsKeywordList(); 00749 FitsKeywordList(const FitsKeywordList &); 00750 FitsKeywordList(ConstFitsKeywordList &); 00751 FitsKeywordList & operator = (const FitsKeywordList &); 00752 00753 // delete the current keyword (the thing returned by curr()) from the list 00754 void del(); 00755 00756 // Add (make) a reserved keyword with the given value and optional comment 00757 // The comment will be truncated if necessary to fit the available space. 00758 // String values must be less than 69 characters. String values longer than 00759 // that will result in an ERROR keyword instead of the desired keyword. 00760 // <group> 00761 void mk(FITS::ReservedName k, Bool v, const char *c = 0); 00762 void mk(FITS::ReservedName k, const char *v = 0, const char *c = 0); 00763 void mk(FITS::ReservedName k, Int v, const char *c = 0); 00764 void mk(FITS::ReservedName k, long v, const char *c = 0); 00765 void mk(FITS::ReservedName k, double v, const char *c = 0); 00766 // </group> 00767 00768 // Add (make) an indexed reserved keyword with the given value and optional comment 00769 // The comment will be truncated if necessary to fit the available space. 00770 // String values must be less than 69 characters. String values longer than 00771 // that will result in an ERROR keyword instead of the desired keyword. 00772 // <group> 00773 void mk(int n, FITS::ReservedName k, Bool v, const char *c = 0); 00774 void mk(int n, FITS::ReservedName k, const char *v, const char *c = 0); 00775 void mk(int n, FITS::ReservedName k, Int v, const char *c = 0); 00776 void mk(int n, FITS::ReservedName k, long v, const char *c = 0); 00777 void mk(int n, FITS::ReservedName k, double v, const char *c = 0); 00778 // </group> 00779 00780 // Add (make) a user defined keyword with the given name, value and optional comment. 00781 // The comment will be truncated if necessary to fit the available space. 00782 // The name must be no longer than 8 characters. Names longer than that will 00783 // result in an ERROR keyword instead of the desired keyword. 00784 // String values must no longer than 69 characters. String values longer than 00785 // that will result in an ERROR keyword instead of the desired keyword. 00786 // <group> 00787 void mk(const char *n, Bool v, const char *c = 0); 00788 void mk(const char *n, const char *v = 0, const char *c = 0); 00789 void mk(const char *n, Int v, const char *c = 0); 00790 void mk(const char *n, long v, const char *c = 0); 00791 void mk(const char *n, float v, const char *c = 0); 00792 void mk(const char *n, double v, const char *c = 0); 00793 void mk(const char *n, Int r, Int i, const char *c = 0); 00794 void mk(const char *n, float r, float i, const char *c = 0); 00795 void mk(const char *n, double r, double i, const char *c = 0); 00796 // </group> 00797 00798 // add a spaces line 00799 void spaces(const char *n = 0, const char *c = 0); 00800 00801 // add a comment card 00802 void comment(const char *n = 0, const char *c = 0); 00803 00804 // add a history card 00805 void history(const char *c = 0); 00806 00807 // add the end card. This must be at the end of the list. 00808 void end(); 00809 00810 // Retrieve specific keywords -- these also set the current mark 00811 //<group> 00812 // return the i-th keyword -- keyword numbering starts with 0 00813 FitsKeyword * operator () (int); 00814 // return first and next non-indexed reserved keyword 00815 FitsKeyword * operator () (const FITS::ReservedName &); 00816 FitsKeyword * next(const FITS::ReservedName &); 00817 // return first and next indexed reserved keyword 00818 FitsKeyword * operator () (const FITS::ReservedName &, int); 00819 FitsKeyword * next(const FITS::ReservedName &, int); 00820 // return first and next user-defined keyword 00821 FitsKeyword * operator () (const char *); 00822 FitsKeyword * next(const char *); 00823 //</group> 00824 00825 //<group> 00826 Bool isempty() const; 00827 void first(); 00828 void last(); 00829 FitsKeyword *next(); 00830 FitsKeyword *prev(); 00831 FitsKeyword *curr(); 00832 //</group> 00833 00834 //<group> 00835 void delete_all(); 00836 int rules(FitsKeyword &, 00837 FITSErrorHandler errhandler = FITSError::defaultHandler); 00838 int rules(FITSErrorHandler errhandler = FITSError::defaultHandler); 00839 Bool basic_rules(); 00840 //</group> 00841 00842 //<group> 00843 // For parsing a single string 00844 void parse(const char *, int); 00845 int no_parse_errs() const; 00846 const char *parse_err(int) const; 00847 //</group> 00848 00849 void insert(FitsKeyword &); 00850 private: 00851 FitsKeyword *beg_; 00852 FitsKeyword *end_; 00853 FitsKeyword *pos; 00854 int total; 00855 int cursor; 00856 FitsKeyword &make(const char *nm, 00857 FITS::ValueType t, const void *v, const char *c); 00858 FitsKeyword &make(FITS::ReservedName nm, 00859 FITS::ValueType t, const void *v, const char *c); 00860 FitsKeyword &make(int ind, FITS::ReservedName nm, 00861 FITS::ValueType t, const void *v, const char *c); 00862 // construct an error keyword - this happens when a name is invalid (NULL 00863 // or more than 8 characters) or a string value is too long (more than 00864 // 69 characters). It is the responsibility of the caller to the 00865 // several mk functions to ensure that that doesn't happen. By the time 00866 // it gets here, it is assumed that such problems are true errors. 00867 // This is used by the private make functions. 00868 FitsKeyword &makeErrKeyword(const char *name, FITS::ValueType type, 00869 const void *val, const char *errmsg); 00870 FitsParse card; 00871 }; 00872 00873 ostream & operator << (ostream &o, FitsKeywordList &); // print the entire list 00874 00875 inline FitsKeywordList::FitsKeywordList() : beg_(0), end_(0), pos(0), 00876 total(0), cursor(0) { } 00877 inline FitsKeywordList::~FitsKeywordList() { delete_all(); } 00878 inline Bool FitsKeywordList::isempty() const { return total == 0 ? True : False; } 00879 inline void FitsKeywordList::first() { cursor = 0; pos = beg_; } 00880 inline void FitsKeywordList::last() { cursor = total; pos = end_; } 00881 inline FitsKeyword *FitsKeywordList::curr() { return pos; } 00882 inline FitsKeyword *FitsKeywordList::operator () (const FITS::ReservedName &n) { 00883 first(); return next(n); } 00884 inline FitsKeyword *FitsKeywordList::operator () (const FITS::ReservedName &n, 00885 int ndx) { first(); return next(n,ndx); } 00886 inline FitsKeyword *FitsKeywordList::operator () (const char *w) { 00887 first(); return next(w); } 00888 inline void FitsKeywordList::parse(const char *s, int l) { 00889 insert(card.parse(s,l)); } 00890 inline int FitsKeywordList::no_parse_errs() const { return card.no_errs();} 00891 inline const char *FitsKeywordList::parse_err(int n) const { 00892 return card.err(n); } 00893 00894 // FitsKeyword constructors for non-indexed Reserved keywords 00895 inline void FitsKeywordList::mk(FITS::ReservedName k, Bool v, const char *c) { 00896 insert(make(k,FITS::LOGICAL,&v,c)); } 00897 inline void FitsKeywordList::mk(FITS::ReservedName k, const char *v, 00898 const char *c) { insert(make(k,FITS::STRING,v,c)); } 00899 inline void FitsKeywordList::mk(FITS::ReservedName k, Int v, const char *c) { 00900 insert(make(k,FITS::LONG,&v,c)); } 00901 inline void FitsKeywordList::mk(FITS::ReservedName k, long v, const char *c) { 00902 insert(make(k,FITS::LONG,&v,c)); } 00903 inline void FitsKeywordList::mk(FITS::ReservedName k, double v, const char *c) { 00904 insert(make(k,FITS::DOUBLE,&v,c)); } 00905 // FitsKeyword constructors for indexed Reserved keywords 00906 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, Bool v, 00907 const char *c) { 00908 Bool tmp; tmp = v; insert(make(n,k,FITS::LOGICAL,&tmp,c)); } 00909 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, const char *v, 00910 const char *c) { insert(make(n,k,FITS::STRING,v,c)); } 00911 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, Int v, 00912 const char *c) { insert(make(n,k,FITS::LONG,&v,c)); } 00913 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, long v, 00914 const char *c) { insert(make(n,k,FITS::LONG,&v,c)); } 00915 inline void FitsKeywordList::mk(int n, FITS::ReservedName k, double v, 00916 const char *c) { insert(make(n,k,FITS::DOUBLE,&v,c)); } 00917 // FitsKeyword constructors for User-Defined keywords 00918 inline void FitsKeywordList::mk(const char *n, Bool v, const char *c) { 00919 Bool tmp; tmp = v; insert(make(n,FITS::LOGICAL,&tmp,c)); } 00920 inline void FitsKeywordList::mk(const char *n, const char *v, const char *c) { 00921 insert(make(n,FITS::STRING,v,c)); } 00922 inline void FitsKeywordList::mk(const char *n, Int v, const char *c) { 00923 insert(make(n,FITS::LONG,&v,c)); } 00924 inline void FitsKeywordList::mk(const char *n, long v, const char *c) { 00925 insert(make(n,FITS::LONG,&v,c)); } 00926 inline void FitsKeywordList::mk(const char *n, float v, const char *c) { 00927 insert(make(n,FITS::FLOAT,&v,c)); } 00928 inline void FitsKeywordList::mk(const char *n, double v, const char *c) { 00929 insert(make(n,FITS::DOUBLE,&v,c)); } 00930 inline void FitsKeywordList::mk(const char *n, Int r, Int i, const char *c) { 00931 IComplex v(r,i); 00932 insert(make(n,FITS::ICOMPLEX,&v,c)); } 00933 inline void FitsKeywordList::mk(const char *n, float r, float i, const char *c) 00934 { Complex v(r,i); insert(make(n,FITS::COMPLEX,&v,c)); } 00935 inline void FitsKeywordList::mk(const char *n, double r, double i, 00936 const char *c) { DComplex v(r,i); 00937 insert(make(n,FITS::DCOMPLEX,&v,c)); } 00938 // Additional keyword constructors for commentary, etc. 00939 inline void FitsKeywordList::spaces(const char *n, const char *c) { 00940 insert((n == 0 ? make(FITS::SPACES,FITS::NOVALUE,0,c) : 00941 (c == 0 ? make(FITS::SPACES,FITS::NOVALUE,0,n) : 00942 make(n,FITS::NOVALUE,0,c)))); } 00943 inline void FitsKeywordList::comment(const char *n, const char *c) { 00944 insert((n == 0 ? make(FITS::COMMENT,FITS::NOVALUE,0,c) : 00945 (c == 0 ? make(FITS::COMMENT,FITS::NOVALUE,0,n) : 00946 make(n,FITS::NOVALUE,0,c)))); } 00947 inline void FitsKeywordList::history(const char *c) { 00948 insert(make(FITS::HISTORY,FITS::NOVALUE,0,c)); } 00949 inline void FitsKeywordList::end() { 00950 insert(make(FITS::END,FITS::NOVALUE,0,0)); } 00951 00952 //<summary> list of read-only FITS keywords </summary> 00953 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00954 // </reviewed> 00955 00956 class ConstFitsKeywordList { 00957 public: 00958 ConstFitsKeywordList(FitsKeywordList &x) : kw(x) { } 00959 00960 const FitsKeyword * operator () (int n) { return kw(n); } 00961 const FitsKeyword * operator () (const FITS::ReservedName &x) { 00962 return kw(x); } 00963 const FitsKeyword * next(const FITS::ReservedName &x) { 00964 return kw.next(x); } 00965 const FitsKeyword * operator () (const FITS::ReservedName &x, int n) { 00966 return kw(x,n); } 00967 const FitsKeyword * next(const FITS::ReservedName &x, int n) { 00968 return kw.next(x,n); } 00969 const FitsKeyword * operator () (const char *x) { return kw(x); } 00970 const FitsKeyword * next(const char *x) { return kw.next(x); } 00971 00972 Bool isempty() const { return kw.isempty(); } 00973 void first() { kw.first(); } 00974 void last() { kw.last(); } 00975 const FitsKeyword *next() { return kw.next(); } 00976 const FitsKeyword *prev() { return kw.prev(); } 00977 const FitsKeyword *curr() { return kw.curr(); } 00978 00979 private: 00980 FitsKeywordList &kw; 00981 }; 00982 00983 //<summary> translator between Keyword lists and fixed FITS cars </summary> 00984 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00985 // </reviewed> 00986 //<synopsis> 00987 // also contains the parser ??? 00988 //</synopsis> 00989 00990 class FitsKeyCardTranslator { 00991 public: 00992 FitsKeyCardTranslator(int = 100); 00993 ~FitsKeyCardTranslator(); 00994 FitsKeywordList & parse(const char *, 00995 FitsKeywordList &, int, FITSErrorHandler, Bool); 00996 int build(char *, FitsKeywordList &); 00997 int no_errs() const; 00998 const char *err(int) const; 00999 int err_cardno(int) const; 01000 private: 01001 int cardno; // the current card number within record 01002 const int FitsCardSize; 01003 const int FitsMaxCard; 01004 const int FitsRecSize; 01005 int max_errs; 01006 int no_errs_; 01007 const char **err_; 01008 int *err_cardno_; 01009 void fmtcard(char *, const FitsKeyword &); 01010 char *blanks; 01011 }; 01012 01013 inline FitsKeyCardTranslator::~FitsKeyCardTranslator() { 01014 delete [] err_; delete [] err_cardno_; delete [] blanks; } 01015 inline int FitsKeyCardTranslator::no_errs() const { return no_errs_; } 01016 inline const char *FitsKeyCardTranslator::err(int i) const { return err_[i]; } 01017 inline int FitsKeyCardTranslator::err_cardno(int i) const { 01018 return err_cardno_[i]; } 01019 01020 // <summary>Utility functions for floating point values</summary> 01021 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 01022 // </reviewed> 01023 class FitsFPUtil 01024 { 01025 public: 01026 // These functions are useful to tell if some type is a floating point type. 01027 // This is useful in a templated function, where the processing can vary 01028 // depending on whether the type is FP or not (e.g. blank handling). 01029 // <group> 01030 static Bool isFP(const float *); 01031 static Bool isFP(const double *); 01032 static Bool isFP(const void *); 01033 // </group> 01034 01035 // For blanking purposes, we need to be able to get a NaN. The NaN we set 01036 // is all bits on. 01037 // <group> 01038 static void setNaN(double &val); 01039 static void setNaN(float &val); 01040 // </group> 01041 }; 01042 01043 01044 } //# NAMESPACE CASA - END 01045 01046 # endif