CCfits  2.5
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 
59 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
60  template<>
61  inline double& Keyword::value(double& val) const
62  {
63  switch (m_keytype)
64  {
65  case Tint:
66  {
67  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
68  val = thisKey.keyval();
69  }
70  break;
71  case Tfloat:
72  {
73  const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
74  val = thisKey.keyval();
75  }
76  break;
77  case Tdouble:
78  {
79  // Note: if val is of type float some precision will be lost here,
80  // but allow anyway. Presumably the user doesn't mind or they
81  // wouldn't be using single precision.
82  const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
83  val = thisKey.keyval();
84  }
85  break;
86  case Tstring:
87  {
88  // Allow only if string can be converted to an integer.
89  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
90  std::istringstream testStream(thisKey.keyval());
91  int stringInt = 0;
92  if (!(testStream >> stringInt) || !testStream.eof())
93  {
94  throw Keyword::WrongKeywordValueType(name());
95  }
96  val = stringInt;
97  }
98  break;
99  default:
100  throw Keyword::WrongKeywordValueType(name());
101  break;
102  }
103  return val;
104  }
105 
106  // NOTE: This function actually instantiates Keyword::value<double>
107  // and therefore must be defined AFTER the specialized
108  // definition/declaration.
109  template<>
110  inline float& Keyword::value(float& val) const
111  {
112  double dval=.0;
113  val = static_cast<float>(value(dval));
114  return val;
115  }
116 
117  template <>
118  inline int& Keyword::value(int& val) const
119  {
120  if (m_keytype == Tstring)
121  {
122  // Allow only if string can be converted to an integer.
123  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
124  std::istringstream testStream(thisKey.keyval());
125  int stringInt = 0;
126  if (!(testStream >> stringInt) || !testStream.eof())
127  {
128  throw Keyword::WrongKeywordValueType(name());
129  }
130  val = stringInt;
131  }
132  else if (m_keytype == Tint)
133  {
134  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
135  val = thisKey.keyval();
136  }
137  else
138  {
139  throw Keyword::WrongKeywordValueType(name());
140  }
141  return val;
142  }
143 
144  template <>
145  inline String& Keyword::value(String& val) const
146  {
147  switch (m_keytype)
148  {
149  case Tint:
150  {
151  const KeyData<int>& thisKey = static_cast<const KeyData<int>&>(*this);
152  std::ostringstream oss;
153  oss << thisKey.keyval();
154  val = oss.str();
155  }
156  break;
157  case Tfloat:
158  {
159  const KeyData<float>& thisKey = static_cast<const KeyData<float>&>(*this);
160  std::ostringstream oss;
161  oss << thisKey.keyval();
162  val = oss.str();
163  }
164  break;
165  case Tdouble:
166  {
167  const KeyData<double>& thisKey = static_cast<const KeyData<double>&>(*this);
168  std::ostringstream oss;
169  oss << thisKey.keyval();
170  val = oss.str();
171  }
172  break;
173  case Tstring:
174  {
175  const KeyData<String>& thisKey = static_cast<const KeyData<String>&>(*this);
176  val = thisKey.keyval();
177  }
178  break;
179  default:
180  throw Keyword::WrongKeywordValueType(name());
181  }
182  return val;
183  }
184 
185 
186  template <>
187  inline void Keyword::setValue(const float& newValue)
188  {
189  if (m_keytype == Tfloat)
190  {
191  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
192  thisKey.keyval(newValue);
193  thisKey.write();
194  }
195  else if (m_keytype == Tdouble)
196  {
197  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
198  thisKey.keyval(static_cast<double>(newValue));
199  thisKey.write();
200  }
201  else
202  {
203  throw Keyword::WrongKeywordValueType(name());
204  }
205  }
206 
207  template <>
208  inline void Keyword::setValue(const double& newValue)
209  {
210  if (m_keytype == Tdouble)
211  {
212  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
213  thisKey.keyval(newValue);
214  thisKey.write();
215  }
216  else if (m_keytype == Tfloat)
217  {
218  // This will lose precision but allow it anyway.
219  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
220  thisKey.keyval(static_cast<float>(newValue));
221  thisKey.write();
222  }
223  else
224  {
225  throw Keyword::WrongKeywordValueType(name());
226  }
227 
228  }
229 
230  template <>
231  inline void Keyword::setValue(const int& newValue)
232  {
233  if (m_keytype == Tint)
234  {
235  KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
236  thisKey.keyval(newValue);
237  thisKey.write();
238  }
239  else if (m_keytype == Tfloat)
240  {
241  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
242  thisKey.keyval(static_cast<float>(newValue));
243  thisKey.write();
244  }
245  else if (m_keytype == Tdouble)
246  {
247  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
248  thisKey.keyval(static_cast<double>(newValue));
249  thisKey.write();
250  }
251  else if (m_keytype == Tstring)
252  {
253  KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
254  std::ostringstream oss;
255  oss << newValue;
256  thisKey.keyval(oss.str());
257  thisKey.write();
258  }
259  else
260  {
261  throw Keyword::WrongKeywordValueType(name());
262  }
263 
264  }
265 
266 
267 
268 #endif
269 } // namespace CCfits
270 
271 #endif
T & value(T &val) const
get the keyword value
Definition: KeywordT.h:29
const String & name() const
return the name of a keyword
Definition: Keyword.h:314
Namespace enclosing all CCfits classes and globals definitions.
Definition: AsciiTable.cxx:26
void setValue(const T &newValue)
modify the value of an existing Keyword and write it to the file
Definition: KeywordT.h:44