CCfits  2.7
KeywordT.h
00001 //  Astrophysics Science Division,
00002 //  NASA/ Goddard Space Flight Center
00003 //  HEASARC
00004 //  http://heasarc.gsfc.nasa.gov
00005 //  e-mail: ccfits@legacy.gsfc.nasa.gov
00006 //
00007 //  Original author: Ben Dorman
00008 
00009 #ifndef KEYWORDT_H
00010 #define KEYWORDT_H
00011 #include "KeyData.h"
00012 #include "HDU.h"
00013 #include <typeinfo>
00014 #include <sstream>
00015 
00016 #ifdef _MSC_VER
00017 #include "MSconfig.h"
00018 #endif
00019 
00020 // contains definitions of templated member functions for Keyword. This separate
00021 // file organization is necessary to break cyclic dependency of Keyword on its
00022 // subclass, KeyData.
00023 
00024 
00025 namespace CCfits 
00026 {
00027 
00028   template <typename T>
00029   T& Keyword::value (T& val) const
00030   {
00031     try
00032     {
00033       const KeyData<T>& thisKey = dynamic_cast<const KeyData<T>&>(*this);
00034       val = thisKey.keyval();
00035     }
00036     catch (std::bad_cast&)
00037     {
00038       throw Keyword::WrongKeywordValueType(name());
00039     }
00040     return val;
00041   }
00042 
00043   template <typename T>
00044   void Keyword::setValue (const T& newValue)
00045   {
00046     try
00047     {
00048       KeyData<T>& thisKey = dynamic_cast<KeyData<T>&>(*this);
00049       thisKey.keyval(newValue);
00050       thisKey.write();
00051     }
00052     catch (std::bad_cast&)
00053     {
00054       throw Keyword::WrongKeywordValueType(name());
00055     }
00056   }
00057 
00058 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00059    template<>
00060    inline double& Keyword::value(double& val) const
00061    {
00062       switch (m_keytype)
00063       {
00064          case Tint:
00065             {
00066                const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00067                val = thisKey.keyval();
00068             }
00069             break;
00070          case Tfloat:
00071             {
00072                const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
00073                val = thisKey.keyval();
00074             }
00075             break;
00076          case Tdouble:
00077             {
00078                // Note: if val is of type float some precision will be lost here,
00079                // but allow anyway.  Presumably the user doesn't mind or they
00080                // wouldn't be using single precision.
00081                const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
00082                val = thisKey.keyval();
00083             }
00084             break;
00085          case Tstring:
00086             {
00087                // Allow only if string can be converted to an integer.
00088                const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this); 
00089                std::istringstream testStream(thisKey.keyval());
00090                int stringInt = 0;
00091                if (!(testStream >> stringInt) || !testStream.eof())
00092                {
00093                   throw Keyword::WrongKeywordValueType(name());
00094                }
00095                val = stringInt;
00096             }
00097             break;
00098          default:
00099             throw Keyword::WrongKeywordValueType(name());
00100             break;
00101       }
00102       return val;
00103    }
00104 
00105    // NOTE: This function actually instantiates Keyword::value<double>
00106    // and therefore must be defined AFTER the specialized 
00107    // definition/declaration.
00108    template<>
00109    inline float& Keyword::value(float& val) const
00110    {
00111       double dval=.0;
00112       val = static_cast<float>(value(dval));
00113       return val;
00114    }
00115 
00116    template <>
00117    inline int& Keyword::value(int& val) const
00118    {
00119          if (m_keytype == Tstring)
00120          {
00121             // Allow only if string can be converted to an integer.
00122             const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this); 
00123             std::istringstream testStream(thisKey.keyval());
00124             int stringInt = 0;
00125             if (!(testStream >> stringInt) || !testStream.eof())
00126             {
00127                throw Keyword::WrongKeywordValueType(name());
00128             }
00129             val = stringInt;         
00130          } 
00131          else if (m_keytype == Tint)
00132          {
00133             const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00134             val = thisKey.keyval();
00135          } 
00136          else
00137          {
00138             throw Keyword::WrongKeywordValueType(name());
00139          }
00140          return val;    
00141    }
00142 
00143    template <>
00144    inline String& Keyword::value(String& val) const
00145    {
00146       switch (m_keytype)
00147       {
00148          case Tint:
00149            {
00150               const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00151               std::ostringstream oss;
00152               oss << thisKey.keyval();
00153               val = oss.str();              
00154            }
00155             break;
00156          case Tfloat:
00157            {
00158               const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
00159               std::ostringstream oss;
00160               oss << thisKey.keyval();
00161               val = oss.str();              
00162            }
00163             break;
00164          case Tdouble:
00165            {
00166               const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
00167               std::ostringstream oss;
00168               oss << thisKey.keyval();
00169               val = oss.str();              
00170            }
00171             break;
00172          case Tstring:
00173            {
00174               const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
00175               val = thisKey.keyval();
00176            }
00177             break;
00178          default:
00179             throw Keyword::WrongKeywordValueType(name());
00180       }
00181       return val;
00182    }
00183 
00184 
00185    template <>
00186    inline void Keyword::setValue(const float& newValue)
00187    {
00188       if (m_keytype == Tfloat)
00189       {
00190          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00191          thisKey.keyval(newValue);
00192          thisKey.write();
00193       }
00194       else if (m_keytype == Tdouble)
00195       {
00196          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00197          thisKey.keyval(static_cast<double>(newValue));
00198          thisKey.write();
00199       }
00200       else
00201       {
00202          throw Keyword::WrongKeywordValueType(name());
00203       }
00204    }
00205 
00206    template <>
00207    inline void Keyword::setValue(const double& newValue)
00208    {
00209       if (m_keytype == Tdouble)
00210       {
00211          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00212          thisKey.keyval(newValue);
00213          thisKey.write();
00214       }
00215       else if (m_keytype == Tfloat)
00216       {
00217          // This will lose precision but allow it anyway.
00218          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00219          thisKey.keyval(static_cast<float>(newValue));
00220          thisKey.write();
00221       }
00222       else
00223       {
00224          throw Keyword::WrongKeywordValueType(name());
00225       }
00226 
00227    }
00228 
00229    template <>
00230    inline void Keyword::setValue(const int& newValue)
00231    {
00232       if (m_keytype == Tint)
00233       {
00234          KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
00235          thisKey.keyval(newValue);
00236          thisKey.write();
00237       }
00238       else if (m_keytype == Tfloat)
00239       {
00240          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00241          thisKey.keyval(static_cast<float>(newValue));
00242          thisKey.write();
00243       }
00244       else if (m_keytype == Tdouble)
00245       {
00246          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00247          thisKey.keyval(static_cast<double>(newValue));
00248          thisKey.write();
00249       }
00250       else if (m_keytype == Tstring)
00251       {
00252          KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
00253          std::ostringstream oss;
00254          oss << newValue;
00255          thisKey.keyval(oss.str());
00256          thisKey.write();
00257       }
00258       else
00259       {
00260          throw Keyword::WrongKeywordValueType(name());
00261       }
00262 
00263    }
00264    
00265 
00266 
00267 #endif
00268 } // namespace CCfits
00269 
00270 #endif