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