CCfits  2.6
KeywordT.h
1 // Astrophysics Science Division,
2 // NASA/ Goddard Space Flight Center
3 // HEASARC
4 // http://heasarc.gsfc.nasa.gov
5 // e-mail: ccfits@legacy.gsfc.nasa.gov
6 //
7 // Original author: Ben Dorman
8 
9 #ifndef KEYWORDT_H
10 #define KEYWORDT_H
11 #include "KeyData.h"
12 #include "HDU.h"
13 #include <typeinfo>
14 #include <sstream>
15 
16 #ifdef _MSC_VER
17 #include "MSconfig.h"
18 #endif
19 
20 // contains definitions of templated member functions for Keyword. This separate
21 // file organization is necessary to break cyclic dependency of Keyword on its
22 // subclass, KeyData.
23 
24 
25 namespace CCfits
26 {
27 
28  template <typename T>
29  T& Keyword::value (T& val) const
30  {
31  try
32  {
33  const KeyData<T>& thisKey = dynamic_cast<const KeyData<T>&>(*this);
34  val = thisKey.keyval();
35  }
36  catch (std::bad_cast&)
37  {
38  throw Keyword::WrongKeywordValueType(name());
39  }
40  return val;
41  }
42 
43  template <typename T>
44  void Keyword::setValue (const T& newValue)
45  {
46  try
47  {
48  KeyData<T>& thisKey = dynamic_cast<KeyData<T>&>(*this);
49  thisKey.keyval(newValue);
50  thisKey.write();
51  }
52  catch (std::bad_cast&)
53  {
54  throw Keyword::WrongKeywordValueType(name());
55  }
56  }
57 
58 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
59  template<>
60  inline double& Keyword::value(double& val) const
61  {
62  switch (m_keytype)
63  {
64  case Tint:
65  {
66  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
67  val = thisKey.keyval();
68  }
69  break;
70  case Tfloat:
71  {
72  const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
73  val = thisKey.keyval();
74  }
75  break;
76  case Tdouble:
77  {
78  // Note: if val is of type float some precision will be lost here,
79  // but allow anyway. Presumably the user doesn't mind or they
80  // wouldn't be using single precision.
81  const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
82  val = thisKey.keyval();
83  }
84  break;
85  case Tstring:
86  {
87  // Allow only if string can be converted to an integer.
88  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
89  std::istringstream testStream(thisKey.keyval());
90  int stringInt = 0;
91  if (!(testStream >> stringInt) || !testStream.eof())
92  {
93  throw Keyword::WrongKeywordValueType(name());
94  }
95  val = stringInt;
96  }
97  break;
98  default:
99  throw Keyword::WrongKeywordValueType(name());
100  break;
101  }
102  return val;
103  }
104 
105  // NOTE: This function actually instantiates Keyword::value<double>
106  // and therefore must be defined AFTER the specialized
107  // definition/declaration.
108  template<>
109  inline float& Keyword::value(float& val) const
110  {
111  double dval=.0;
112  val = static_cast<float>(value(dval));
113  return val;
114  }
115 
116  template <>
117  inline int& Keyword::value(int& val) const
118  {
119  if (m_keytype == Tstring)
120  {
121  // Allow only if string can be converted to an integer.
122  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
123  std::istringstream testStream(thisKey.keyval());
124  int stringInt = 0;
125  if (!(testStream >> stringInt) || !testStream.eof())
126  {
127  throw Keyword::WrongKeywordValueType(name());
128  }
129  val = stringInt;
130  }
131  else if (m_keytype == Tint)
132  {
133  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
134  val = thisKey.keyval();
135  }
136  else
137  {
138  throw Keyword::WrongKeywordValueType(name());
139  }
140  return val;
141  }
142 
143  template <>
144  inline String& Keyword::value(String& val) const
145  {
146  switch (m_keytype)
147  {
148  case Tint:
149  {
150  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
151  std::ostringstream oss;
152  oss << thisKey.keyval();
153  val = oss.str();
154  }
155  break;
156  case Tfloat:
157  {
158  const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
159  std::ostringstream oss;
160  oss << thisKey.keyval();
161  val = oss.str();
162  }
163  break;
164  case Tdouble:
165  {
166  const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
167  std::ostringstream oss;
168  oss << thisKey.keyval();
169  val = oss.str();
170  }
171  break;
172  case Tstring:
173  {
174  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
175  val = thisKey.keyval();
176  }
177  break;
178  default:
179  throw Keyword::WrongKeywordValueType(name());
180  }
181  return val;
182  }
183 
184 
185  template <>
186  inline void Keyword::setValue(const float& newValue)
187  {
188  if (m_keytype == Tfloat)
189  {
190  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
191  thisKey.keyval(newValue);
192  thisKey.write();
193  }
194  else if (m_keytype == Tdouble)
195  {
196  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
197  thisKey.keyval(static_cast<double>(newValue));
198  thisKey.write();
199  }
200  else
201  {
202  throw Keyword::WrongKeywordValueType(name());
203  }
204  }
205 
206  template <>
207  inline void Keyword::setValue(const double& newValue)
208  {
209  if (m_keytype == Tdouble)
210  {
211  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
212  thisKey.keyval(newValue);
213  thisKey.write();
214  }
215  else if (m_keytype == Tfloat)
216  {
217  // This will lose precision but allow it anyway.
218  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
219  thisKey.keyval(static_cast<float>(newValue));
220  thisKey.write();
221  }
222  else
223  {
224  throw Keyword::WrongKeywordValueType(name());
225  }
226 
227  }
228 
229  template <>
230  inline void Keyword::setValue(const int& newValue)
231  {
232  if (m_keytype == Tint)
233  {
234  KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
235  thisKey.keyval(newValue);
236  thisKey.write();
237  }
238  else if (m_keytype == Tfloat)
239  {
240  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
241  thisKey.keyval(static_cast<float>(newValue));
242  thisKey.write();
243  }
244  else if (m_keytype == Tdouble)
245  {
246  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
247  thisKey.keyval(static_cast<double>(newValue));
248  thisKey.write();
249  }
250  else if (m_keytype == Tstring)
251  {
252  KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
253  std::ostringstream oss;
254  oss << newValue;
255  thisKey.keyval(oss.str());
256  thisKey.write();
257  }
258  else
259  {
260  throw Keyword::WrongKeywordValueType(name());
261  }
262 
263  }
264 
265 
266 
267 #endif
268 } // namespace CCfits
269 
270 #endif
const String & name() const
return the name of a keyword
Definition: Keyword.h:320
T & value(T &val) const
get the keyword value
Definition: KeywordT.h:29
void setValue(const T &newValue)
modify the value of an existing Keyword and write it to the file
Definition: KeywordT.h:44