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