CCfits
2.4
|
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