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
37namespace Euclid {
38namespace Table {
39
40template <typename To>
41class CastVisitor : public boost::static_visitor<To> {
42
43public:
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
56template <>
57class CastVisitor<std::string> : public boost::static_visitor<std::string> {
58
59public:
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
68template <>
69class CastVisitor<double> : public boost::static_visitor<double> {
70
71 template <typename From>
72 static constexpr bool generic() {
74 }
75
76public:
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
103template <>
104class CastVisitor<float> : public boost::static_visitor<float> {
105
106 template <typename From>
107 static constexpr bool generic() {
110 }
111
112public:
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
139template <>
140class CastVisitor<int64_t> : public boost::static_visitor<int64_t> {
141
142 template <typename From>
143 static constexpr bool generic() {
145 }
146
147public:
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
170template <>
171class CastVisitor<int32_t> : public boost::static_visitor<int32_t> {
172
173 template <typename From>
174 static constexpr bool generic() {
177 }
178
179public:
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
206template <typename VectorType>
207class CastVisitor<std::vector<VectorType>> : public boost::static_visitor<std::vector<VectorType>> {
208
209public:
210 template <typename From>
211 std::vector<VectorType> operator()(const From& from) const {
213 result.push_back(CastVisitor<VectorType>{}(from));
214 return result;
215 }
216
217 template <typename From>
220 for (auto v : from) {
222 }
223 return result;
224 }
225
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::string &from) const
Definition: CastVisitor.h:226
std::vector< VectorType > operator()(const std::vector< From > &from) const
Definition: CastVisitor.h:218
std::vector< VectorType > operator()(const From &from) const
Definition: CastVisitor.h:211
const std::vector< VectorType > & operator()(const std::vector< VectorType > &from) const
Definition: CastVisitor.h:237
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)