diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2020-03-23 20:10:08 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2020-03-23 20:10:08 (GMT) |
commit | 42027570f57b484414d4e87f19e9c26aed5bb71d (patch) | |
tree | 4ce4812d4a348d147cf3d388106272101ccffc2a /fitsy/column.C | |
parent | 1ea3cd7a5f436d8baa13fb53007773dcee637bd1 (diff) | |
download | blt-42027570f57b484414d4e87f19e9c26aed5bb71d.zip blt-42027570f57b484414d4e87f19e9c26aed5bb71d.tar.gz blt-42027570f57b484414d4e87f19e9c26aed5bb71d.tar.bz2 |
libutil
Diffstat (limited to 'fitsy/column.C')
-rw-r--r-- | fitsy/column.C | 671 |
1 files changed, 671 insertions, 0 deletions
diff --git a/fitsy/column.C b/fitsy/column.C new file mode 100644 index 0000000..b6052ab --- /dev/null +++ b/fitsy/column.C @@ -0,0 +1,671 @@ +// Copyright (C) 1999-2018 +// Smithsonian Astrophysical Observatory, Cambridge, MA, USA +// For conditions of distribution and use, see copyright notice in "copyright" + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <float.h> + +#include <iostream> +#include <sstream> +#include <iomanip> +using namespace std; + +#include "column.h" +#include "file.h" +#include "head.h" +#include "util.h" + +FitsColumn::FitsColumn(FitsHead* head, int i, int off) +{ + index_ = i; + width_ = 0; + offset_ = off; + type_ = ' '; + + tform_ = dupstr(head->getString(keycat("TFORM",i))); + ttype_ = dupstr(head->getString(keycat("TTYPE",i))); + tunit_ = dupstr(head->getString(keycat("TUNIT",i))); + tscal_ = head->getReal(keycat("TSCAL",i), 1); + tzero_ = head->getReal(keycat("TZERO",i), 0); + hastnull_ = head->find(keycat("TNULL",i)) ? 1:0; + tnull_ = head->getInteger(keycat("TNULL",i), 0); + + char* td = head->find(keycat("TDMAX",i)); + char* tl = head->find(keycat("TLMAX",i)); + char* ta = head->find(keycat("TALEN",i)); + char* ax = head->find(keycat("AXLEN",i)); + + // this provides backward compatibility + if (td) { + hastlmin_ = head->find(keycat("TDMIN",i)) ? 1:0; + hastlmax_ = 1; + tlmin_ = head->getReal(keycat("TDMIN",i), 0); + tlmax_ = head->getReal(keycat("TDMAX",i), 0); + } + else if (tl) { + hastlmin_ = head->find(keycat("TLMIN",i)) ? 1:0; + hastlmax_ = 1; + tlmin_ = head->getReal(keycat("TLMIN",i), 0); + tlmax_ = head->getReal(keycat("TLMAX",i), 0); + } + else if (ta) { + hastlmin_ = 0; + hastlmax_ = 1; + tlmin_ = 1; + tlmax_ = head->getReal(keycat("TALEN",i), 0); + } + else if (ax) { + hastlmin_ = 0; + hastlmax_ = 1; + tlmin_ = 1; + tlmax_ = head->getReal(keycat("AXLEN",i), 0); + } + else { + hastlmin_ = 0; + hastlmax_ = 0; + tlmin_ = 0; + tlmax_ = 0; + } + + // now, make sure they are valid + if (tlmin_>tlmax_) { + hastlmin_ = 0; + hastlmax_ = 0; + tlmin_ = 0; + tlmax_ = 0; + } + + // use tlmin/tlmax if available + if (hastlmin_ || hastlmax_) { + min_ = tlmin_; + max_ = tlmax_; + } + else { + min_ = -DBL_MAX; + max_ = DBL_MAX; + } +} + +FitsColumn::~FitsColumn() +{ + if (tform_) + delete [] tform_; + if (tunit_) + delete [] tunit_; + if (ttype_) + delete [] ttype_; +} + +char* FitsColumn::keycat(const char* name, int i) +{ + ostringstream str; + str << name << i << ends; + memcpy(keybuf,str.str().c_str(),str.str().length()); + return keybuf; +} + +// FitsAsciiColumn + +FitsAsciiColumn::FitsAsciiColumn(FitsHead* head, int i, int offset) + : FitsColumn(head, i, offset) +{ + int tbcol = head->getInteger(keycat("TBCOL",i),0); + if (tbcol) + offset_ = tbcol-1; +} + +char* FitsAsciiColumn::str(const char* ptr, int i) +{ + strncpy(buf_, ptr+offset_, width_); + buf_[width_] = '\0'; + return buf_; +} + +FitsAsciiColumnStr::FitsAsciiColumnStr(FitsHead* head, int i, int offset) + : FitsAsciiColumn(head, i, offset) +{ + if (tform_) { + string x(tform_); + istringstream str(x); + str >> type_ >> width_; + } +} + +FitsAsciiColumnA::FitsAsciiColumnA(FitsHead* head, int i, int offset) + : FitsAsciiColumn(head, i, offset) +{ + prec_ = 0; + + if (tform_) { + char s; + string x(tform_); + istringstream str(x); + str >> type_ >> width_ >> s >> prec_; + } +} + +double FitsAsciiColumnA::value(const char* ptr, int i) +{ + string x(ptr+offset_); + istringstream str(x); + double r; + str >> r; + + return r; +} + +template<class T> FitsAsciiColumnT<T>::FitsAsciiColumnT(FitsHead* head, + int i, int off) + : FitsAsciiColumnA(head, i, off) {} + +template <> Vector FitsAsciiColumnT<int>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_,tlmax_) + : Vector(INT_MIN,INT_MAX); +} + +template <> Vector FitsAsciiColumnT<float>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_,tlmax_) + : Vector(-FLT_MAX,FLT_MAX); +} + +template <> Vector FitsAsciiColumnT<double>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_,tlmax_) + : Vector(-DBL_MAX,DBL_MAX); +} + +// FitsBinColumn + +FitsBinColumn::FitsBinColumn(FitsHead* head, int i, int offset) + : FitsColumn(head, i, offset) +{ + tdisp_ = dupstr(head->getString(keycat("TDISP",i))); + + repeat_ = 1; + if (tform_) { + string x(tform_); + istringstream str(x); + if (isalpha(tform_[0])) + str >> type_; + else + str >> repeat_ >> type_; + } + + tdim_ = dupstr(head->getString(keycat("TDIM",i))); + tdimM_ =0; + tdimK_ =NULL; + char dummy; + if (tdim_) { + string x(tdim_); + istringstream str(x); + str >> dummy >> tdimM_; + if (tdimM_>0) { + tdimK_ = new int[tdimM_]; + for (int ii=0; ii<tdimM_; ii++) + str >> dummy >> tdimK_[ii]; + } + } +} + +FitsBinColumn::~FitsBinColumn() +{ + if (tdisp_) + delete [] tdisp_; + + if (tdim_) + delete [] tdim_; + + if (tdimK_) + delete [] tdimK_; +} + +// FitsBinColumnStr + +FitsBinColumnStr::FitsBinColumnStr(FitsHead* head, int i, int offset) + : FitsBinColumn(head, i, offset) +{ + width_ = repeat_; +} + +char* FitsBinColumnStr::str(const char* ptr, int i) +{ + strncpy(buf_, ptr+offset_, width_); + buf_[width_] = '\0'; + return buf_; +} + +// FitsBinColumnLogical + +FitsBinColumnLogical::FitsBinColumnLogical(FitsHead* head, int i, int offset) + : FitsBinColumn(head, i, offset) +{ + width_ = repeat_; +} + +char* FitsBinColumnLogical::str(const char* ptr, int i) +{ + strncpy(buf_, ptr+offset_+i, 1); + buf_[width_] = '\0'; + return buf_; +} + +// FitsBinColumnArray + +FitsBinColumnArray::FitsBinColumnArray(FitsHead* head, int i, int offset) + : FitsBinColumn(head, i, offset) +{ + ptype_ = ' '; + psize_ = 1; + pmax_ = 1; + abuf_ = NULL; + + byteswap_ = lsb(); + + if (tform_) { + int rr; + char tt; + string x(tform_); + istringstream str(x); + if (isalpha(tform_[0])) + str >> tt; + else + str >> rr >> tt; + + char s; + str >> ptype_ >> s >> pmax_ >> s; + + switch (ptype_) { + case 'L': + psize_ = 1; + break; + case 'X': + psize_ = 1; + break; + case 'B': + psize_ = 1; + break; + case 'I': + psize_ = 2; + break; + case 'J': + psize_ = 4; + break; + case 'K': + psize_ = 8; + break; + case 'A': + psize_ = 1; + break; + case 'E': + psize_ = 4; + break; + case 'D': + psize_ = 8; + break; + case 'C': + psize_ = 8; + break; + case 'M': + psize_ = 16; + break; + + default: + internalError("Fitsy++ column unknown table column type."); + return; + } + + // sanity check + pmax_ *= psize_; + + if (pmax_ > 0) + abuf_ = new char[pmax_]; + } +} + +FitsBinColumnArray::~FitsBinColumnArray() +{ + if (abuf_) + delete [] abuf_; +} + +void* FitsBinColumnArray::get(const char* heap, const char* ptr, int* cnt) +{ + *cnt = swap(ptr,0); + if (*cnt > pmax_) { + // just in case + internalError("Fitsy++ column variable array size greater than specified"); + *cnt = pmax_; + } + size_t pp = swap(ptr,1); + + if (abuf_) { + memset(abuf_,0,pmax_); + memcpy(abuf_,heap+pp,(*cnt)*psize_); + } + + return abuf_; +} + +FitsBinColumnArrayP::FitsBinColumnArrayP(FitsHead* head, int i, int offset) + : FitsBinColumnArray(head, i, offset) +{ + width_ = 8; +} + +int FitsBinColumnArrayP::swap(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*4; + union { + char c[4]; + int i; + } u; + + if (byteswap_) { + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,4); + + return u.i; +} + +FitsBinColumnArrayQ::FitsBinColumnArrayQ(FitsHead* head, int i, int offset) + : FitsBinColumnArray(head, i, offset) +{ + width_ = 16; +} + +int FitsBinColumnArrayQ::swap(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*8; + union { + char c[8]; + long l; + } u; + + if (byteswap_) { + u.c[7] = *p++; + u.c[6] = *p++; + u.c[5] = *p++; + u.c[4] = *p++; + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,8); + + return u.l; +} + +// FitsbinColumnBit + +FitsBinColumnBit::FitsBinColumnBit(FitsHead* head, int i, int off) + : FitsBinColumn(head, i, off) +{ + width_ = (repeat_+7)/8; +} + +// FitsBinColumnB + +FitsBinColumnB::FitsBinColumnB(FitsHead* head, int i, int offset) + : FitsBinColumn(head, i, offset) +{ + byteswap_ = lsb(); +} + +// FitsBinColumnT + +template<class T> FitsBinColumnT<T>::FitsBinColumnT(FitsHead* head, + int i, int off) + : FitsBinColumnB(head, i, off) +{ + width_ = repeat_ * sizeof(T); +} + +template <> double FitsBinColumnT<unsigned char>::value(const char* ptr, int i) +{ + return (unsigned char)(*(ptr+offset_+i)); +} + +template <> double FitsBinColumnT<short>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*2; + union { + char c[2]; + short s; + } u; + + if (byteswap_) { + u.c[1] = *p++; + u.c[0] = *p; + } + else { + u.c[0] = *p++; + u.c[1] = *p; + } + + return u.s; +} + +template <> double FitsBinColumnT<unsigned short>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*2; + union { + char c[2]; + unsigned short s; + } u; + + if (byteswap_) { + u.c[1] = *p++; + u.c[0] = *p; + } + else { + u.c[0] = *p++; + u.c[1] = *p; + } + + return u.s; +} + +template <> double FitsBinColumnT<int>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*4; + union { + char c[4]; + int i; + } u; + + if (byteswap_) { + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,4); + + return u.i; +} + +template <> double FitsBinColumnT<unsigned int>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*4; + union { + char c[4]; + unsigned int i; + } u; + + if (byteswap_) { + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,4); + + return u.i; +} + +template <> double FitsBinColumnT<long long>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*8; + union { + char c[8]; + long long i; + } u; + + if (byteswap_) { + u.c[7] = *p++; + u.c[6] = *p++; + u.c[5] = *p++; + u.c[4] = *p++; + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,8); + + return u.i; +} + +template <> double FitsBinColumnT<float>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*4; + union { + char c[4]; + float f; + } u; + + if (byteswap_) { + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,4); + + return u.f; +} + +template <> double FitsBinColumnT<double>::value(const char* ptr, int i) +{ + const char* p = ptr+offset_+i*8; + union { + char c[8]; + double d; + } u; + + if (byteswap_) { + u.c[7] = *p++; + u.c[6] = *p++; + u.c[5] = *p++; + u.c[4] = *p++; + u.c[3] = *p++; + u.c[2] = *p++; + u.c[1] = *p++; + u.c[0] = *p; + } + else + memcpy(u.c,p,8); + + return u.d; +} + +template<class T> char* FitsBinColumnT<T>::str(const char* ptr, int i) +{ + ostringstream ost; + ost << value(ptr,i) << ends; + return (char*)dupstr(ost.str().c_str()); +} + +template <> Vector FitsBinColumnT<unsigned char>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(0,UCHAR_MAX); +} + +template <> Vector FitsBinColumnT<short>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(SHRT_MIN,SHRT_MAX); +} + +template <> Vector FitsBinColumnT<unsigned short>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(0,USHRT_MAX); +} + +template <> Vector FitsBinColumnT<int>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(INT_MIN,INT_MAX); +} + +template <> Vector FitsBinColumnT<unsigned int>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(0,UINT_MAX); +} + +// some older versions of gcc do not have LLONG +#ifndef LLONG_MIN +# ifdef LONG_LONG_MIN +# define LLONG_MIN LONG_LONG_MIN +# else +# define LLONG_MIN LONG_MIN +# endif +#endif + +#ifndef LLONG_MAX +# ifdef LONG_LONG_MAX +# define LLONG_MAX LONG_LONG_MAX +# else +# define LLONG_MAX LONG_MAX +# endif +#endif + +template <> Vector FitsBinColumnT<long long>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_-.5,tlmax_+.5) + : Vector(LLONG_MIN,LLONG_MAX); +} + +template <> Vector FitsBinColumnT<float>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_,tlmax_) + : Vector(-FLT_MAX,FLT_MAX); +} + +template <> Vector FitsBinColumnT<double>::dimension() +{ + return (hastlmin_ || hastlmax_) ? Vector(tlmin_,tlmax_) + : Vector(-DBL_MAX,DBL_MAX); +} + +template class FitsAsciiColumnT<int>; +template class FitsAsciiColumnT<float>; +template class FitsAsciiColumnT<double>; + +template class FitsBinColumnT<unsigned char>; +template class FitsBinColumnT<short>; +template class FitsBinColumnT<unsigned short>; +template class FitsBinColumnT<int>; +template class FitsBinColumnT<unsigned int>; +template class FitsBinColumnT<long long>; +template class FitsBinColumnT<float>; +template class FitsBinColumnT<double>; |