// Copyright (C) 1999-2017 // Smithsonian Astrophysical Observatory, Cambridge, MA, USA // For conditions of distribution and use, see copyright notice in "copyright" #include #include #include #include #ifndef __WIN32 #include #include #endif #include "file.h" #include "head.h" FitsHead::FitsHead(char* raw, size_t bytes, Memory mem) { cards_ = raw; mapdata_ = raw; mapsize_ = bytes; memory_ = mem; ncard_ = 0; acard_ = 0; ccard_ = 0; index_ = NULL; valid_ = 0; inherit_ = 0; hdu_ = NULL; char* c; int i; for (c = cards_, i=0; c < cards_+bytes; c+=FTY_CARDLEN, i++) { // only compare 4 chars if (!strncmp(c, "END ", 4)) { ncard_ = i + 1; acard_ = ((ncard_+FTY_CARDS-1)/FTY_CARDS) * FTY_CARDS; valid_ = 1; buildIndex(); updateHDU(); return; } } } FitsHead::FitsHead(char* raw, size_t bytes, char* mm, size_t sz, Memory mem) { cards_ = raw; mapdata_ = mm; mapsize_ = sz; memory_ = mem; ncard_ = 0; acard_ = 0; ccard_ = 0; index_ = NULL; valid_ = 0; inherit_ = 0; hdu_ = NULL; char* c; int i; for (c = cards_, i=0; c < cards_+bytes; c+=FTY_CARDLEN, i++) { // only compare 4 chars if (!strncmp(c, "END ", 4)) { ncard_ = i + 1; acard_ = ((ncard_+FTY_CARDS-1)/FTY_CARDS) * FTY_CARDS; valid_ = 1; buildIndex(); updateHDU(); return; } } } // Create Image FitsHead FitsHead::FitsHead(int width, int height, int depth, int bitpix, char* xtension) { cards_ = new char[FTY_BLOCK]; memset(cards_, ' ', FTY_BLOCK); memcpy(cards_, "END", 3); mapdata_ = NULL; mapsize_ = 0; memory_ = ALLOC; ncard_ = 1; acard_ = FTY_CARDS; ccard_ = 0; index_ = NULL; if (!xtension) appendLogical("SIMPLE", 1, "Fits Standard"); else appendString("XTENSION", xtension, "Fits Standard"); appendInteger("BITPIX", bitpix, "Bits per pixel"); appendInteger("NAXIS", depth>1 ? 3 : 2, "Number of axes"); appendInteger("NAXIS1", width, "Axis Length"); appendInteger("NAXIS2", height, "Axis Length"); if (depth>1) appendInteger("NAXIS3", depth, "Axis Length"); valid_ = 1; inherit_ = 0; hdu_ = NULL; buildIndex(); updateHDU(); } FitsHead::FitsHead(int width, int height, int depth, int bitpix, char* mm, size_t sz, Memory mem) { cards_ = new char[FTY_BLOCK]; memset(cards_, ' ', FTY_BLOCK); memcpy(cards_, "END", 3); mapdata_ = mm; mapsize_ = sz; memory_ = mem; ncard_ = 1; acard_ = FTY_CARDS; ccard_ = 0; index_ = NULL; appendLogical("SIMPLE", 1, "Fits Standard"); appendInteger("BITPIX", bitpix, "Bits per pixel"); appendInteger("NAXIS", depth==1 ? 2 : 3, "Number of axes"); appendInteger("NAXIS1", width, "Axis Length"); appendInteger("NAXIS2", height, "Axis Length"); if (depth>1) appendInteger("NAXIS3", depth, "Axis Length"); valid_ = 1; inherit_ = 0; hdu_ = NULL; buildIndex(); updateHDU(); } FitsHead::FitsHead(const FitsHead& a) { cards_ = new char[a.acard_*FTY_CARDLEN]; memmove(cards_, a.cards_, a.acard_*FTY_CARDLEN); mapdata_ = NULL; mapsize_ = 0; memory_ = ALLOC; index_ = NULL; acard_ = a.acard_; ncard_ = a.ncard_; ccard_ = a.ccard_; valid_ = 1; inherit_ = 0; hdu_ = NULL; buildIndex(); updateHDU(); } FitsHead::~FitsHead() { if (index_) delete [] index_; if (hdu_) delete hdu_; switch (memory_) { case ALLOC: if (cards_) delete [] cards_; break; case MMAP: #ifndef __WIN32 if (mapdata_) munmap((caddr_t)mapdata_, mapsize_); #endif break; case SHARE: #ifndef __WIN32 if (mapdata_) shmdt(mapdata_); #endif case EXTERNAL: break; } } int FitsHead::isImage() { // just look for SIMPLE, if present it may be of value 'F' char* xtension = getString("XTENSION"); char* simple = find("SIMPLE"); int r = (simple || (xtension && !strncmp(xtension, "IMAGE", 5))) && naxes() > 0 && naxis(0) > 0 && naxis(1) > 0; return r; } int FitsHead::isTable() { char* xtension = getString("XTENSION"); int r = (xtension && (!strncmp(xtension, "TABLE", 5) || !strncmp(xtension, "BINTABLE", 8))); return r; } int FitsHead::isAsciiTable() { char* xtension = getString("XTENSION"); int r = (xtension && (!strncmp(xtension, "TABLE", 5))); return r; } int FitsHead::isBinTable() { char* xtension = getString("XTENSION"); int r = (xtension && (!strncmp(xtension, "BINTABLE", 8))); return r; } int FitsHead::isHeap() { return getInteger("PCOUNT",0) ? 1 : 0; } void FitsHead::updateHDU() { if (hdu_) delete hdu_; hdu_ = NULL; // just find simple, it might be present but of value 'F' char* simple = find("SIMPLE"); char* xtension = getString("XTENSION"); if (xtension) inherit_ = getLogical("INHERIT",0); if (simple || (xtension && !strncmp(xtension, "IMAGE", 5))) hdu_ = new FitsImageHDU(this); if (xtension && !strncmp(xtension, "TABLE", 5)) hdu_ = new FitsAsciiTableHDU(this); if (xtension && !strncmp(xtension, "BINTABLE", 8)) hdu_ = new FitsBinTableHDU(this); } int FitsHead::getLogical(const char* name, int def) { char* card = find(name); if (card) { FitsCard c(card); return c.getLogical(); } else return def; } int FitsHead::getInteger(const char* name, int def) { char* card = find(name); if (card) { FitsCard c(card); return c.getInteger(); } else return def; } double FitsHead::getReal(const char* name, double def) { char* card = find(name); if (card) { FitsCard c(card); return c.getReal(); } else return def; } void FitsHead::getComplex(const char* name, double* real, double* img, double rdef, double idef) { char* card = find(name); if (card) { FitsCard c(card); c.getComplex(real, img); } else { *real = rdef; *img = idef; } } char* FitsHead::getString(const char* name) { char* card = find(name); if (card) { FitsCard c(card); return c.getString(); } else return NULL; } char* FitsHead::getComment(const char* name) { char* card = find(name); if (card) { FitsCard c(card); return c.getComment(); } else return NULL; } char* FitsHead::getKeyword(const char* name) { char* card = find(name); if (card) { FitsCard c(card); return c.getKeyword(); } else return NULL; } char* FitsHead::setKey(const char* name, const char* value) { char* card = find(name); if (card) FitsCard(card).setKey(value); buildIndex(); return card; } char* FitsHead::setLogical(const char* name, int value, const char* comm) { char* card = find(name); if (card) FitsCard(card).setLogical(value, comm); return card; } char* FitsHead::setInteger(const char* name, int value, const char* comm) { char* card = find(name); if (card) FitsCard(card).setInteger(value, comm); return card; } char* FitsHead::setReal(const char* name, double value, int prec, const char* comm) { char* card = find(name); if (card) FitsCard(card).setReal(value, prec, comm); return card; } char* FitsHead::setComplex(const char* name, double real, double img, int prec, const char* comm) { char* card = find(name); if (card) FitsCard(card).setComplex(real, img, prec, comm); return card; } char* FitsHead::setString(const char* name, const char* value, const char* comm) { char* card = find(name); if (card) FitsCard(card).setString(value, comm); return card; } char* FitsHead::setComment(const char* name, const char* value) { char* card = find(name); if (card) FitsCard(card).setComment(value); return card; } char* FitsHead::cardins(char* card, char* here) { // do we need to allocate another block? if (ncard_+1 > acard_) { switch (memory_) { case ALLOC: { char* old = cards_; int oldsz = acard_*FTY_CARDLEN; int sz = oldsz+FTY_BLOCK; acard_ = sz/FTY_CARDLEN; cards_ = new char[sz]; memset(cards_, ' ', sz); memcpy(cards_, old, oldsz); // don't forget to redirect here if needed if (here) { size_t diff = here-old; here = cards_+diff; } delete [] old; } break; case MMAP: case SHARE: case EXTERNAL: internalError("Fitsy++ head can't add card: readonly memory"); return NULL; } } char* where = here ? here : cards_+((ncard_-1)*FTY_CARDLEN); memmove(where+FTY_CARDLEN, where, (cards_+(ncard_*FTY_CARDLEN))-where); memmove(where, card, FTY_CARDLEN); ncard_++; buildIndex(); return where; } char* FitsHead::carddel(const char* name) { char* card = find(name); if (card) { char* next = card+FTY_CARDLEN; char* last = cards_+((ncard_-1)*FTY_CARDLEN); memmove(card, next, last-card); memset(last,' ', FTY_CARDLEN); } buildIndex(); return card; } char* FitsHead::cardclear(const char* name) { char* card = find(name); if (card) FitsCard(card).clear(); buildIndex(); return card; } char* FitsHead::insertLogical(const char* name, int value, const char* comm, const char* here) { FitsCard key; key.setLogical(name, value, comm); return cardins(key.card(), (char*)here); } char* FitsHead::insertInteger(const char* name, int value, const char* comm, const char* here) { FitsCard key; key.setInteger(name, value, comm); return cardins(key.card(), (char*)here); } char* FitsHead::insertReal(const char* name, double value, int prec, const char* comm, const char* here) { FitsCard key; key.setReal(name, value, prec, comm); return cardins(key.card(), (char*)here); } char* FitsHead::insertComplex(const char* name, double real, double img, int prec, const char* comm, const char* here) { FitsCard key; key.setComplex(name, real, img, prec, comm); return cardins(key.card(), (char*)here); } char* FitsHead::insertString(const char* name, const char* value, const char* comm, const char* here) { FitsCard key; key.setString(name, value, comm); return cardins(key.card(), (char*)here); } char* FitsHead::insertComment(const char* name, const char* value, const char* here) { FitsCard key; key.setComment(name, value); return cardins(key.card(), (char*)here); } char* FitsHead::first() { ccard_ = 0; return (ccard_8 ? 8 : len); for (int i=0; i8 ? 8 : len); for (int i=0; i 1) { int i = strncmp(k, base[cut], 8); if (!i) return base[cut]; if (i < 0) { hi = cut; cut = (lo+hi)/2; } else { lo = cut; cut = (lo+hi)/2; } } if (!strncmp(k, base[cut], 8)) return base[cut]; return NULL; } static int compare(const void* a, const void* b) { char** aa = (char**)a; char** bb = (char**)b; return strncmp(*aa, *bb, 8); } void FitsHead::buildIndex() { if (index_) delete [] index_; index_ = new char*[ncard_]; for (int i=0; i