Alexandria  2.25.0
SDC-CH common library for the Euclid project
CastVisitor.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2021 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 
29 #include <boost/tokenizer.hpp>
30 #include <boost/variant/static_visitor.hpp>
31 #include <cmath>
32 #include <sstream>
33 #include <type_traits>
34 #include <typeinfo>
35 #include <vector>
36 
37 namespace Euclid {
38 namespace Table {
39 
40 template <typename To>
41 class CastVisitor : public boost::static_visitor<To> {
42 
43 public:
44  template <typename From>
45  To operator()(const From& from, typename std::enable_if<std::is_same<From, To>::value>::type* = 0) const {
46  return from;
47  }
48 
49  template <typename From>
50  To operator()(const From&, typename std::enable_if<!std::is_same<From, To>::value>::type* = 0) const {
51  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
52  << typeid(To).name();
53  }
54 };
55 
56 template <>
57 class CastVisitor<std::string> : public boost::static_visitor<std::string> {
58 
59 public:
60  template <typename From>
61  std::string operator()(const From& from) const {
62  std::stringstream result{};
63  result << from;
64  return result.str();
65  }
66 };
67 
68 template <>
69 class CastVisitor<double> : public boost::static_visitor<double> {
70 
71  template <typename From>
72  static constexpr bool generic() {
74  }
75 
76 public:
77  template <typename From>
78  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
79  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
80  << typeid(double).name();
81  }
82 
83  template <typename From>
84  double operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
85  return from;
86  }
87 
88  double operator()(const std::string& from) const {
89  char* endptr = nullptr;
90  double value = std::strtod(from.c_str(), &endptr);
91  if (endptr == from.c_str()) {
92  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
93  << typeid(double).name();
94  }
95  if (value == HUGE_VAL || value == -HUGE_VAL) {
96  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
97  << typeid(double).name();
98  }
99  return value;
100  }
101 };
102 
103 template <>
104 class CastVisitor<float> : public boost::static_visitor<float> {
105 
106  template <typename From>
107  static constexpr bool generic() {
110  }
111 
112 public:
113  template <typename From>
114  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
115  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
116  << typeid(float).name();
117  }
118 
119  template <typename From>
120  float operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
121  return from;
122  }
123 
124  float operator()(const std::string& from) const {
125  char* endptr = nullptr;
126  float value = std::strtof(from.c_str(), &endptr);
127  if (endptr == from.c_str()) {
128  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
129  << typeid(float).name();
130  }
131  if (value == HUGE_VALF || value == -HUGE_VALF) {
132  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
133  << typeid(float).name();
134  }
135  return value;
136  }
137 };
138 
139 template <>
140 class CastVisitor<int64_t> : public boost::static_visitor<int64_t> {
141 
142  template <typename From>
143  static constexpr bool generic() {
145  }
146 
147 public:
148  template <typename From>
149  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
150  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
151  << typeid(int64_t).name();
152  }
153 
154  template <typename From>
155  int64_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
156  return from;
157  }
158 
159  int64_t operator()(const std::string& from) const {
160  char* endptr = nullptr;
161  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
162  if (endptr == from.c_str()) {
163  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
164  << typeid(int64_t).name();
165  }
166  return value;
167  }
168 };
169 
170 template <>
171 class CastVisitor<int32_t> : public boost::static_visitor<int32_t> {
172 
173  template <typename From>
174  static constexpr bool generic() {
177  }
178 
179 public:
180  template <typename From>
181  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
182  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to "
183  << typeid(int32_t).name();
184  }
185 
186  template <typename From>
187  int32_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
188  return from;
189  }
190 
191  int32_t operator()(const std::string& from) const {
192  char* endptr = nullptr;
193  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
194  if (endptr == from.c_str()) {
195  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to "
196  << typeid(int32_t).name();
197  }
198  if (value > INT32_MAX || value < INT32_MIN) {
199  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to "
200  << typeid(int32_t).name();
201  }
202  return static_cast<int32_t>(value);
203  }
204 };
205 
206 template <typename VectorType>
207 class CastVisitor<std::vector<VectorType>> : public boost::static_visitor<std::vector<VectorType>> {
208 
209 public:
210  template <typename From>
211  std::vector<VectorType> operator()(const From& from) const {
212  std::vector<VectorType> result{};
213  result.push_back(CastVisitor<VectorType>{}(from));
214  return result;
215  }
216 
217  template <typename From>
219  std::vector<VectorType> result{};
220  for (auto v : from) {
221  result.push_back(CastVisitor<VectorType>{}(v));
222  }
223  return result;
224  }
225 
227  std::vector<VectorType> result{};
228  boost::char_separator<char> sep{","};
229  boost::tokenizer<boost::char_separator<char>> tok{from, sep};
230  for (auto& s : tok) {
232  }
233  return result;
234  }
235 
236  // If the types match exactly we avoid an expensive copying
238  return from;
239  }
240 };
241 
242 } /* namespace Table */
243 } /* namespace Euclid */
244 
245 #endif
T c_str(T... args)
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:78
double operator()(const std::string &from) const
Definition: CastVisitor.h:88
double operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:84
float operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:120
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:114
float operator()(const std::string &from) const
Definition: CastVisitor.h:124
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:181
int32_t operator()(const std::string &from) const
Definition: CastVisitor.h:191
int32_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:187
int64_t operator()(const std::string &from) const
Definition: CastVisitor.h:159
int64_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:155
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:149
std::string operator()(const From &from) const
Definition: CastVisitor.h:61
std::vector< VectorType > operator()(const std::vector< From > &from) const
Definition: CastVisitor.h:218
const std::vector< VectorType > & operator()(const std::vector< VectorType > &from) const
Definition: CastVisitor.h:237
std::vector< VectorType > operator()(const From &from) const
Definition: CastVisitor.h:211
std::vector< VectorType > operator()(const std::string &from) const
Definition: CastVisitor.h:226
To operator()(const From &, typename std::enable_if<!std::is_same< From, To >::value >::type *=0) const
Definition: CastVisitor.h:50
To operator()(const From &from, typename std::enable_if< std::is_same< From, To >::value >::type *=0) const
Definition: CastVisitor.h:45
constexpr double s
STL namespace.
T push_back(T... args)
T str(T... args)
T strtod(T... args)
T strtoll(T... args)