Alexandria  2.19
Please provide a description of the 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 " << typeid(To).name();
52  }
53 };
54 
55 template <>
56 class CastVisitor<std::string> : public boost::static_visitor<std::string> {
57 
58 public:
59  template <typename From>
60  std::string operator()(const From& from) const {
61  std::stringstream result{};
62  result << from;
63  return result.str();
64  }
65 };
66 
67 template <>
68 class CastVisitor<double> : public boost::static_visitor<double> {
69 
70  template <typename From>
71  static constexpr bool generic() {
73  }
74 
75 public:
76  template <typename From>
77  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
78  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to " << typeid(double).name();
79  }
80 
81  template <typename From>
82  double operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
83  return from;
84  }
85 
86  double operator()(const std::string& from) const {
87  char* endptr = nullptr;
88  double value = std::strtod(from.c_str(), &endptr);
89  if (endptr == from.c_str()) {
90  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to " << typeid(double).name();
91  }
92  if (value == HUGE_VAL || value == -HUGE_VAL) {
93  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to " << typeid(double).name();
94  }
95  return value;
96  }
97 };
98 
99 template <>
100 class CastVisitor<float> : public boost::static_visitor<float> {
101 
102  template <typename From>
103  static constexpr bool generic() {
106  }
107 
108 public:
109  template <typename From>
110  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
111  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to " << typeid(float).name();
112  }
113 
114  template <typename From>
115  float operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
116  return from;
117  }
118 
119  float operator()(const std::string& from) const {
120  char* endptr = nullptr;
121  float value = std::strtof(from.c_str(), &endptr);
122  if (endptr == from.c_str()) {
123  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to " << typeid(float).name();
124  }
125  if (value == HUGE_VALF || value == -HUGE_VALF) {
126  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to " << typeid(float).name();
127  }
128  return value;
129  }
130 };
131 
132 template <>
133 class CastVisitor<int64_t> : public boost::static_visitor<int64_t> {
134 
135  template <typename From>
136  static constexpr bool generic() {
138  }
139 
140 public:
141  template <typename From>
142  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
143  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to " << typeid(int64_t).name();
144  }
145 
146  template <typename From>
147  int64_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
148  return from;
149  }
150 
151  int64_t operator()(const std::string& from) const {
152  char* endptr = nullptr;
153  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
154  if (endptr == from.c_str()) {
155  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to " << typeid(int64_t).name();
156  }
157  return value;
158  }
159 };
160 
161 template <>
162 class CastVisitor<int32_t> : public boost::static_visitor<int32_t> {
163 
164  template <typename From>
165  static constexpr bool generic() {
168  }
169 
170 public:
171  template <typename From>
172  double operator()(const From&, typename std::enable_if<!generic<From>()>::type* = 0) const {
173  throw Elements::Exception() << "CastVisitor cannot convert " << typeid(From).name() << " type to " << typeid(int32_t).name();
174  }
175 
176  template <typename From>
177  int32_t operator()(const From& from, typename std::enable_if<generic<From>()>::type* = 0) const {
178  return from;
179  }
180 
181  int32_t operator()(const std::string& from) const {
182  char* endptr = nullptr;
183  int64_t value = std::strtoll(from.c_str(), &endptr, 10);
184  if (endptr == from.c_str()) {
185  throw Elements::Exception() << "CastVisitor cannot convert the string '" << from << "' to " << typeid(int32_t).name();
186  }
187  if (value > INT32_MAX || value < INT32_MIN) {
188  throw Elements::Exception() << "CastVisitor overflows converting the string '" << from << "' to " << typeid(int32_t).name();
189  }
190  return static_cast<int32_t>(value);
191  }
192 };
193 
194 template <typename VectorType>
195 class CastVisitor<std::vector<VectorType>> : public boost::static_visitor<std::vector<VectorType>> {
196 
197 public:
198  template <typename From>
199  std::vector<VectorType> operator()(const From& from) const {
200  std::vector<VectorType> result{};
201  result.push_back(CastVisitor<VectorType>{}(from));
202  return result;
203  }
204 
205  template <typename From>
207  std::vector<VectorType> result{};
208  for (auto v : from) {
209  result.push_back(CastVisitor<VectorType>{}(v));
210  }
211  return result;
212  }
213 
215  std::vector<VectorType> result{};
216  boost::char_separator<char> sep{","};
217  boost::tokenizer<boost::char_separator<char>> tok{from, sep};
218  for (auto& s : tok) {
220  }
221  return result;
222  }
223 
224  // If the types match exactly we avoid an expensive copying
226  return from;
227  }
228 };
229 
230 } /* namespace Table */
231 } /* namespace Euclid */
232 
233 #endif
T c_str(T... args)
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:77
double operator()(const std::string &from) const
Definition: CastVisitor.h:86
double operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:82
float operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:115
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:110
float operator()(const std::string &from) const
Definition: CastVisitor.h:119
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:172
int32_t operator()(const std::string &from) const
Definition: CastVisitor.h:181
int32_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:177
int64_t operator()(const std::string &from) const
Definition: CastVisitor.h:151
int64_t operator()(const From &from, typename std::enable_if< generic< From >()>::type *=0) const
Definition: CastVisitor.h:147
double operator()(const From &, typename std::enable_if<!generic< From >()>::type *=0) const
Definition: CastVisitor.h:142
std::string operator()(const From &from) const
Definition: CastVisitor.h:60
std::vector< VectorType > operator()(const std::vector< From > &from) const
Definition: CastVisitor.h:206
const std::vector< VectorType > & operator()(const std::vector< VectorType > &from) const
Definition: CastVisitor.h:225
std::vector< VectorType > operator()(const From &from) const
Definition: CastVisitor.h:199
std::vector< VectorType > operator()(const std::string &from) const
Definition: CastVisitor.h:214
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)