Alexandria  2.14.1
Please provide a description of the project.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
CastVisitor.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
25 #ifndef _TABLE_CASTVISITOR_H
26 #define _TABLE_CASTVISITOR_H
27 
28 #include <sstream>
29 #include <typeinfo>
30 #include <vector>
31 #include <type_traits>
32 #include <boost/variant/static_visitor.hpp>
33 #include <boost/tokenizer.hpp>
34 #include <cmath>
36 
37 namespace Euclid {
38 namespace Table {
39 
40 template <typename To>
41 class CastVisitor : public boost::static_visitor<To> {
42 
43 public:
44 
45  template <typename From>
46  To operator() (const From& from, typename std::enable_if<std::is_same<From, To>::value>::type* = 0) const {
47  return from;
48  }
49 
50  template <typename From>
51  To operator() (const From&, typename std::enable_if<!std::is_same<From, To>::value>::type* = 0) const {
52  throw Elements::Exception() << "CastVisitor cannot convert "
53  << typeid(From).name() << " type to " << typeid(To).name();
54  }
55 
56 };
57 
58 template <>
59 class CastVisitor<std::string> : public boost::static_visitor<std::string> {
60 
61 public:
62 
63  template <typename From>
64  std::string operator() (const From& from) const {
65  std::stringstream result {};
66  result << from;
67  return result.str();
68  }
69 
70 };
71 
72 template <>
73 class CastVisitor<double> : public boost::static_visitor<double> {
74 
75  template <typename From>
76  static constexpr bool generic() {
78  }
79 
80 public:
81 
82  template <typename From>
83  double operator() (const From& , typename std::enable_if<!generic<From>()>::type* = 0) const {
84  throw Elements::Exception() << "CastVisitor cannot convert "
85  << typeid(From).name() << " type to " << typeid(double).name();
86  }
87 
88  template <typename From>
89  double operator() (const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
90  return from;
91  }
92 
93  double operator() (const std::string& from) const {
94  char *endptr = nullptr;
95  double value = std::strtod(from.c_str(), &endptr);
96  if (endptr == from.c_str()) {
97  throw Elements::Exception() << "CastVisitor cannot convert the string '"
98  << from << "' to " << typeid(double).name();
99  }
100  if (value == HUGE_VAL || value == -HUGE_VAL) {
101  throw Elements::Exception() << "CastVisitor overflows converting the string '"
102  << from << "' to " << typeid(double).name();
103  }
104  return value;
105  }
106 
107 };
108 
109 template <>
110 class CastVisitor<float> : public boost::static_visitor<float> {
111 
112  template <typename From>
113  static constexpr bool generic() {
116  }
117 
118 public:
119 
120  template <typename From>
121  double operator() (const From& , typename std::enable_if<!generic<From>()>::type* = 0) const {
122  throw Elements::Exception() << "CastVisitor cannot convert "
123  << typeid(From).name() << " type to " << typeid(float).name();
124  }
125 
126  template <typename From>
127  float operator() (const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
128  return from;
129  }
130 
131  float operator() (const std::string& from) const {
132  char *endptr = nullptr;
133  float value = std::strtof(from.c_str(), &endptr);
134  if (endptr == from.c_str()) {
135  throw Elements::Exception() << "CastVisitor cannot convert the string '"
136  << from << "' to " << typeid(float).name();
137  }
138  if (value == HUGE_VALF || value == -HUGE_VALF) {
139  throw Elements::Exception() << "CastVisitor overflows converting the string '"
140  << from << "' to " << typeid(float).name();
141  }
142  return value;
143  }
144 
145 };
146 
147 template <>
148 class CastVisitor<int64_t> : public boost::static_visitor<int64_t> {
149 
150  template <typename From>
151  static constexpr bool generic() {
153  }
154 
155 public:
156 
157  template <typename From>
158  double operator() (const From& , typename std::enable_if<!generic<From>()>::type* = 0) const {
159  throw Elements::Exception() << "CastVisitor cannot convert "
160  << typeid(From).name() << " type to " << typeid(int64_t).name();
161  }
162 
163  template <typename From>
164  int64_t operator() (const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
165  return from;
166  }
167 
168  int64_t operator() (const std::string& from) const {
169  char *endptr = nullptr;
170  int64_t value = std::strtol(from.c_str(), &endptr, 10);
171  if (endptr == from.c_str()) {
172  throw Elements::Exception() << "CastVisitor cannot convert the string '"
173  << from << "' to " << typeid(int64_t).name();
174  }
175  return value;
176  }
177 
178 };
179 
180 template <>
181 class CastVisitor<int32_t> : public boost::static_visitor<int32_t> {
182 
183  template <typename From>
184  static constexpr bool generic() {
187  }
188 
189 public:
190 
191  template <typename From>
192  double operator() (const From& , typename std::enable_if<!generic<From>()>::type* = 0) const {
193  throw Elements::Exception() << "CastVisitor cannot convert "
194  << typeid(From).name() << " type to " << typeid(int32_t).name();
195  }
196 
197  template <typename From>
198  int32_t operator() (const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
199  return from;
200  }
201 
202  int32_t operator() (const std::string& from) const {
203  char *endptr = nullptr;
204  int64_t value = std::strtol(from.c_str(), &endptr, 10);
205  if (endptr == from.c_str()) {
206  throw Elements::Exception() << "CastVisitor cannot convert the string '"
207  << from << "' to " << typeid(int32_t).name();
208  }
209  if (value > INT32_MAX || value < INT32_MIN) {
210  throw Elements::Exception() << "CastVisitor overflows converting the string '"
211  << from << "' to " << typeid(int32_t).name();
212  }
213  return static_cast<int32_t>(value);
214  }
215 
216 };
217 
218 template <typename VectorType>
219 class CastVisitor<std::vector<VectorType>> : public boost::static_visitor<std::vector<VectorType>> {
220 
221 public:
222 
223  template <typename From>
224  std::vector<VectorType> operator() (const From& from) const {
225  std::vector<VectorType> result {};
226  result.push_back(CastVisitor<VectorType>{}(from));
227  return result;
228  }
229 
230  template <typename From>
231  std::vector<VectorType> operator() (const std::vector<From>& from) const {
232  std::vector<VectorType> result {};
233  for (auto v : from) {
234  result.push_back(CastVisitor<VectorType>{}(v));
235  }
236  return result;
237  }
238 
239  std::vector<VectorType> operator() (const std::string& from) const {
240  std::vector<VectorType> result {};
241  boost::char_separator<char> sep {","};
242  boost::tokenizer< boost::char_separator<char> > tok {from, sep};
243  for (auto& s : tok) {
245  }
246  return result;
247  }
248 
249  // If the types match exactly we avoid an expensive copying
250  const std::vector<VectorType>& operator() (const std::vector<VectorType>& from) const {
251  return from;
252  }
253 
254 };
255 
256 } /* namespace Table */
257 } /* namespace Euclid */
258 
259 
260 #endif
To operator()(const From &from, typename std::enable_if< std::is_same< From, To >::value >::type *=0) const
Definition: CastVisitor.h:46
constexpr double s
STL class.
T push_back(T...args)
T str(T...args)
STL class.
T c_str(T...args)
T strtol(T...args)
T strtod(T...args)