CCfits  2.4
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 
00059 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00060    template<>
00061    inline double& Keyword::value(double& val) const
00062    {
00063       switch (m_keytype)
00064       {
00065          case Tint:
00066             {
00067                const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00068                val = thisKey.keyval();
00069             }
00070             break;
00071          case Tfloat:
00072             {
00073                const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
00074                val = thisKey.keyval();
00075             }
00076             break;
00077          case Tdouble:
00078             {
00079                // Note: if val is of type float some precision will be lost here,
00080                // but allow anyway.  Presumably the user doesn't mind or they
00081                // wouldn't be using single precision.
00082                const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
00083                val = thisKey.keyval();
00084             }
00085             break;
00086          case Tstring:
00087             {
00088                // Allow only if string can be converted to an integer.
00089                const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this); 
00090                std::istringstream testStream(thisKey.keyval());
00091                int stringInt = 0;
00092                if (!(testStream >> stringInt) || !testStream.eof())
00093                {
00094                   throw Keyword::WrongKeywordValueType(name());
00095                }
00096                val = stringInt;
00097             }
00098             break;
00099          default:
00100             throw Keyword::WrongKeywordValueType(name());
00101             break;
00102       }
00103       return val;
00104    }
00105 
00106    // NOTE: This function actually instantiates Keyword::value<double>
00107    // and therefore must be defined AFTER the specialized 
00108    // definition/declaration.
00109    template<>
00110    inline float& Keyword::value(float& val) const
00111    {
00112       double dval=.0;
00113       val = static_cast<float>(value(dval));
00114       return val;
00115    }
00116 
00117    template <>
00118    inline int& Keyword::value(int& val) const
00119    {
00120          if (m_keytype == Tstring)
00121          {
00122             // Allow only if string can be converted to an integer.
00123             const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this); 
00124             std::istringstream testStream(thisKey.keyval());
00125             int stringInt = 0;
00126             if (!(testStream >> stringInt) || !testStream.eof())
00127             {
00128                throw Keyword::WrongKeywordValueType(name());
00129             }
00130             val = stringInt;         
00131          } 
00132          else if (m_keytype == Tint)
00133          {
00134             const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00135             val = thisKey.keyval();
00136          } 
00137          else
00138          {
00139             throw Keyword::WrongKeywordValueType(name());
00140          }
00141          return val;    
00142    }
00143 
00144 
00145    template <>
00146    inline void Keyword::setValue(const float& newValue)
00147    {
00148       if (m_keytype == Tfloat)
00149       {
00150          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00151          thisKey.keyval(newValue);
00152          thisKey.write();
00153       }
00154       else if (m_keytype == Tdouble)
00155       {
00156          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00157          thisKey.keyval(static_cast<double>(newValue));
00158          thisKey.write();
00159       }
00160       else
00161       {
00162          throw Keyword::WrongKeywordValueType(name());
00163       }
00164    }
00165 
00166    template <>
00167    inline void Keyword::setValue(const double& newValue)
00168    {
00169       if (m_keytype == Tdouble)
00170       {
00171          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00172          thisKey.keyval(newValue);
00173          thisKey.write();
00174       }
00175       else if (m_keytype == Tfloat)
00176       {
00177          // This will lose precision but allow it anyway.
00178          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00179          thisKey.keyval(static_cast<float>(newValue));
00180          thisKey.write();
00181       }
00182       else
00183       {
00184          throw Keyword::WrongKeywordValueType(name());
00185       }
00186 
00187    }
00188 
00189    template <>
00190    inline void Keyword::setValue(const int& newValue)
00191    {
00192       if (m_keytype == Tint)
00193       {
00194          KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
00195          thisKey.keyval(newValue);
00196          thisKey.write();
00197       }
00198       else if (m_keytype == Tfloat)
00199       {
00200          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00201          thisKey.keyval(static_cast<float>(newValue));
00202          thisKey.write();
00203       }
00204       else if (m_keytype == Tdouble)
00205       {
00206          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00207          thisKey.keyval(static_cast<double>(newValue));
00208          thisKey.write();
00209       }
00210       else if (m_keytype == Tstring)
00211       {
00212          KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
00213          std::ostringstream oss;
00214          oss << newValue;
00215          thisKey.keyval(oss.str());
00216          thisKey.write();
00217       }
00218       else
00219       {
00220          throw Keyword::WrongKeywordValueType(name());
00221       }
00222 
00223    }
00224 
00225 #endif
00226 } // namespace CCfits
00227 
00228 #endif