CCfits  2.4
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 
145  template <>
146  inline void Keyword::setValue(const float& newValue)
147  {
148  if (m_keytype == Tfloat)
149  {
150  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
151  thisKey.keyval(newValue);
152  thisKey.write();
153  }
154  else if (m_keytype == Tdouble)
155  {
156  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
157  thisKey.keyval(static_cast<double>(newValue));
158  thisKey.write();
159  }
160  else
161  {
162  throw Keyword::WrongKeywordValueType(name());
163  }
164  }
165 
166  template <>
167  inline void Keyword::setValue(const double& newValue)
168  {
169  if (m_keytype == Tdouble)
170  {
171  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
172  thisKey.keyval(newValue);
173  thisKey.write();
174  }
175  else if (m_keytype == Tfloat)
176  {
177  // This will lose precision but allow it anyway.
178  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
179  thisKey.keyval(static_cast<float>(newValue));
180  thisKey.write();
181  }
182  else
183  {
184  throw Keyword::WrongKeywordValueType(name());
185  }
186 
187  }
188 
189  template <>
190  inline void Keyword::setValue(const int& newValue)
191  {
192  if (m_keytype == Tint)
193  {
194  KeyData<int>& thisKey = static_cast<KeyData<int>&>(*this);
195  thisKey.keyval(newValue);
196  thisKey.write();
197  }
198  else if (m_keytype == Tfloat)
199  {
200  KeyData<float>& thisKey = static_cast<KeyData<float>&>(*this);
201  thisKey.keyval(static_cast<float>(newValue));
202  thisKey.write();
203  }
204  else if (m_keytype == Tdouble)
205  {
206  KeyData<double>& thisKey = static_cast<KeyData<double>&>(*this);
207  thisKey.keyval(static_cast<double>(newValue));
208  thisKey.write();
209  }
210  else if (m_keytype == Tstring)
211  {
212  KeyData<String>& thisKey = static_cast<KeyData<String>&>(*this);
213  std::ostringstream oss;
214  oss << newValue;
215  thisKey.keyval(oss.str());
216  thisKey.write();
217  }
218  else
219  {
220  throw Keyword::WrongKeywordValueType(name());
221  }
222 
223  }
224 
225 #endif
226 } // namespace CCfits
227 
228 #endif
const String & name() const
return the name of a keyword
Definition: Keyword.h:312
Namespace enclosing all CCfits classes and globals definitions.
Definition: AsciiTable.cxx:26
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