CCfits  2.5
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    template <>
00145    inline String& Keyword::value(String& val) const
00146    {
00147       switch (m_keytype)
00148       {
00149          case Tint:
00150            {
00151               const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
00152               std::ostringstream oss;
00153               oss << thisKey.keyval();
00154               val = oss.str();              
00155            }
00156             break;
00157          case Tfloat:
00158            {
00159               const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
00160               std::ostringstream oss;
00161               oss << thisKey.keyval();
00162               val = oss.str();              
00163            }
00164             break;
00165          case Tdouble:
00166            {
00167               const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
00168               std::ostringstream oss;
00169               oss << thisKey.keyval();
00170               val = oss.str();              
00171            }
00172             break;
00173          case Tstring:
00174            {
00175               const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
00176               val = thisKey.keyval();
00177            }
00178             break;
00179          default:
00180             throw Keyword::WrongKeywordValueType(name());
00181       }
00182       return val;
00183    }
00184 
00185 
00186    template <>
00187    inline void Keyword::setValue(const float& newValue)
00188    {
00189       if (m_keytype == Tfloat)
00190       {
00191          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00192          thisKey.keyval(newValue);
00193          thisKey.write();
00194       }
00195       else if (m_keytype == Tdouble)
00196       {
00197          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00198          thisKey.keyval(static_cast<double>(newValue));
00199          thisKey.write();
00200       }
00201       else
00202       {
00203          throw Keyword::WrongKeywordValueType(name());
00204       }
00205    }
00206 
00207    template <>
00208    inline void Keyword::setValue(const double& newValue)
00209    {
00210       if (m_keytype == Tdouble)
00211       {
00212          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00213          thisKey.keyval(newValue);
00214          thisKey.write();
00215       }
00216       else if (m_keytype == Tfloat)
00217       {
00218          // This will lose precision but allow it anyway.
00219          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00220          thisKey.keyval(static_cast<float>(newValue));
00221          thisKey.write();
00222       }
00223       else
00224       {
00225          throw Keyword::WrongKeywordValueType(name());
00226       }
00227 
00228    }
00229 
00230    template <>
00231    inline void Keyword::setValue(const int& newValue)
00232    {
00233       if (m_keytype == Tint)
00234       {
00235          KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
00236          thisKey.keyval(newValue);
00237          thisKey.write();
00238       }
00239       else if (m_keytype == Tfloat)
00240       {
00241          KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
00242          thisKey.keyval(static_cast<float>(newValue));
00243          thisKey.write();
00244       }
00245       else if (m_keytype == Tdouble)
00246       {
00247          KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
00248          thisKey.keyval(static_cast<double>(newValue));
00249          thisKey.write();
00250       }
00251       else if (m_keytype == Tstring)
00252       {
00253          KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
00254          std::ostringstream oss;
00255          oss << newValue;
00256          thisKey.keyval(oss.str());
00257          thisKey.write();
00258       }
00259       else
00260       {
00261          throw Keyword::WrongKeywordValueType(name());
00262       }
00263 
00264    }
00265    
00266 
00267 
00268 #endif
00269 } // namespace CCfits
00270 
00271 #endif