Goby v2
as.h
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef STRING20100713H
24 #define STRING20100713H
25 
26 #include <boost/lexical_cast.hpp>
27 #include <iomanip>
28 #include <iostream>
29 #include <limits>
30 #include <sstream>
31 #include <string>
32 #include <vector>
33 
34 #include <boost/algorithm/string.hpp>
35 #include <boost/mpl/and.hpp>
36 #include <boost/mpl/logical.hpp>
37 #include <boost/numeric/conversion/cast.hpp>
38 #include <boost/static_assert.hpp>
39 #include <boost/type_traits.hpp>
40 #include <boost/utility.hpp>
41 
42 namespace goby
43 {
44 namespace util
45 {
47 
48 
49 template <typename To>
50 typename boost::enable_if<boost::is_arithmetic<To>, To>::type
51 _as_from_string(const std::string& from)
52 {
53  try
54  {
55  return boost::lexical_cast<To>(from);
56  }
57  catch (boost::bad_lexical_cast&)
58  {
59  // return NaN or maximum value supported by the type
60  return std::numeric_limits<To>::has_quiet_NaN ? std::numeric_limits<To>::quiet_NaN()
61  : std::numeric_limits<To>::max();
62  }
63 }
64 
65 // only works properly for enums with a defined 0 value
66 template <typename To>
67 typename boost::enable_if<boost::is_enum<To>, To>::type _as_from_string(const std::string& from)
68 {
69  try
70  {
71  return static_cast<To>(boost::lexical_cast<int>(from));
72  }
73  catch (boost::bad_lexical_cast&)
74  {
75  return static_cast<To>(0);
76  }
77 }
78 
79 template <typename To>
80 typename boost::enable_if<boost::is_class<To>, To>::type _as_from_string(const std::string& from)
81 {
82  try
83  {
84  return boost::lexical_cast<To>(from);
85  }
86  catch (boost::bad_lexical_cast&)
87  {
88  return To();
89  }
90 }
91 
92 template <> inline bool _as_from_string<bool>(const std::string& from)
93 {
94  return (boost::iequals(from, "true") || boost::iequals(from, "1"));
95 }
96 
97 template <> inline std::string _as_from_string<std::string>(const std::string& from)
98 {
99  return from;
100 }
101 
102 template <typename To, typename From> std::string _as_to_string(const From& from)
103 {
104  try
105  {
106  return boost::lexical_cast<std::string>(from);
107  }
108  catch (boost::bad_lexical_cast&)
109  {
110  return std::string();
111  }
112 }
113 
115 template <> inline std::string _as_to_string<std::string, bool>(const bool& from)
116 {
117  return from ? "true" : "false";
118 }
119 
120 template <> inline std::string _as_to_string<std::string, std::string>(const std::string& from)
121 {
122  return from;
123 }
124 
125 template <typename To, typename From>
126 typename boost::disable_if<boost::is_same<To, From>, To>::type _as_numeric(const From& from)
127 {
128  try
129  {
130  return boost::numeric_cast<To>(from);
131  }
132  catch (boost::bad_numeric_cast&)
133  {
134  // return NaN or maximum value supported by the type
135  return std::numeric_limits<To>::has_quiet_NaN ? std::numeric_limits<To>::quiet_NaN()
136  : std::numeric_limits<To>::max();
137  }
138 }
139 
140 template <typename To, typename From>
141 typename boost::enable_if<boost::is_same<To, From>, To>::type _as_numeric(const From& from)
142 {
143  return from;
144 }
145 
146 template <typename To> To as(const std::string& from) { return _as_from_string<To>(from); }
147 
148 template <typename To, typename From>
149 typename boost::enable_if<boost::is_same<To, std::string>, To>::type as(const From& from)
150 {
151  return _as_to_string<To, From>(from);
152 }
153 
154 template <typename To, typename From>
155 typename boost::enable_if<boost::mpl::and_<boost::is_arithmetic<To>, boost::is_arithmetic<From> >,
156  To>::type
157 as(const From& from)
158 {
159  return _as_numeric<To, From>(from);
160 }
161 
162 // not much better we can do for enums than static cast them ...
163 template <typename To, typename From>
164 typename boost::enable_if<boost::mpl::and_<boost::is_enum<To>, boost::is_arithmetic<From> >,
165  To>::type
166 as(const From& from)
167 {
168  return static_cast<To>(from);
169 }
170 
171 enum FloatRepresentation
172 {
173  FLOAT_DEFAULT,
174  FLOAT_FIXED,
175  FLOAT_SCIENTIFIC
176 };
177 
178 template <typename To, typename From>
179 To as(const From& from, int precision, FloatRepresentation rep = FLOAT_DEFAULT)
180 {
181  return as<To>(from);
182 }
183 
184 template <>
185 inline std::string as<std::string, double>(const double& from, int precision,
186  FloatRepresentation rep)
187 {
188  std::stringstream out;
189  switch (rep)
190  {
191  case FLOAT_DEFAULT: break;
192 
193  case FLOAT_FIXED: out << std::fixed; break;
194  case FLOAT_SCIENTIFIC: out << std::scientific; break;
195  }
196 
197  out << std::setprecision(precision) << from;
198  return out.str();
199 }
200 
201 template <>
202 inline std::string as<std::string, float>(const float& from, int precision, FloatRepresentation rep)
203 {
204  std::stringstream out;
205  switch (rep)
206  {
207  case FLOAT_DEFAULT: break;
208 
209  case FLOAT_FIXED: out << std::fixed; break;
210  case FLOAT_SCIENTIFIC: out << std::scientific; break;
211  }
212 
213  out << std::setprecision(precision) << from;
214  return out.str();
215 }
216 
217 } // namespace util
218 } // namespace goby
219 #endif
STL namespace.
The global namespace for the Goby project.