The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lexical_cast.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * New lexcical_cast header.
18  *
19  * For debugging you can include this header _in_ a namespace (to honor ODR)
20  * and have a set of functions that throws exceptions instead of doing the
21  * real job. This is done for the unit tests but should normally not be done.
22  */
23 
24 #ifdef LEXICAL_CAST_DEBUG
25 #undef LEXICAL_CAST_HPP_INCLUDED
26 #endif
27 
28 #ifndef LEXICAL_CAST_HPP_INCLUDED
29 #define LEXICAL_CAST_HPP_INCLUDED
30 
31 #ifdef LEXICAL_CAST_DEBUG
32 
33 #undef DEBUG_THROW
34 /**
35  * Throws an exception for debugging.
36  *
37  * @param id The unique name to identify the function.
38  * @note this name is a user defined string and
39  * should not be modified once used!
40  */
41 #define DEBUG_THROW(id) throw id;
42 #else
43 
44 #ifdef __FreeBSD__
45 #define __LONG_LONG_SUPPORTED
46 #endif
47 
48 #ifdef _MSC_VER
49 #define strtoll _strtoi64
50 #define strtoull _strtoui64
51 #endif
52 
53 #include "global.hpp"
54 
55 #include <cstdlib>
56 #include <string>
57 #include <sstream>
58 #include <boost/mpl/set.hpp>
59 #include <boost/type_traits.hpp>
60 #include <boost/utility/enable_if.hpp>
61 
62 #define DEBUG_THROW(id)
63 #endif
64 
65 /**
66  * @namespace implementation
67  * Contains the implementation details for lexical_cast and shouldn't be used
68  * directly.
69  */
70 namespace implementation {
71 
72  template<
73  typename To
74  , typename From
75  , typename ToEnable = void
76  , typename FromEnable = void
77  >
78  struct tlexical_cast;
79 
80 } // namespace implementation
81 
82 /**
83  * Lexical cast converts one type to another.
84  *
85  * @tparam To The type to convert to.
86  * @tparam From The type to convert from.
87  *
88  * @param value The value to convert.
89  *
90  * @returns The converted value.
91  */
92 template<typename To, typename From>
93 inline To lexical_cast(From value)
94 {
95  return implementation::tlexical_cast<To, From>().operator()(value);
96 }
97 
98 /** Thrown when a lexical_cast fails. */
99 struct bad_lexical_cast : std::exception {};
100 
101 namespace implementation {
102 
103 /**
104  * Base class for the conversion.
105  *
106  * Since functions can't be partially specialized we use a class, which can be
107  * partially specialized for the conversion.
108  *
109  * @tparam To The type to convert to.
110  * @tparam From The type to convert from.
111  * @tparam ToEnable Filter to enable the To type.
112  * @tparam FromEnable Filter to enable the From type.
113  */
114 template<
115  typename To
116  , typename From
117  , typename ToEnable
118  , typename FromEnable
119 >
120 struct tlexical_cast
121 {
122  To operator()(From value)
123  {
124  DEBUG_THROW("generic");
125 
126  To result;
127  std::stringstream sstr;
128 
129  if(!(sstr << value && sstr >> result)) {
130  throw bad_lexical_cast();
131  } else {
132  return result;
133  }
134  }
135 };
136 
137 /**
138  * Specialized conversion class.
139  *
140  * Specialized for returning strings from an integral type or a pointer to an
141  * integral type.
142  */
143 template <typename From>
145  std::string
146  , From
147  , void
148  , typename boost::enable_if<boost::is_integral<
149  typename boost::remove_pointer<From>::type> >::type
150 >
151 {
153  {
154  DEBUG_THROW("specialized - To std::string - From integral (pointer)");
155 
156  std::stringstream sstr;
157  sstr << value;
158  return sstr.str();
159  }
160 };
161 
162 /**
163  * Specialized conversion class.
164  *
165  * Specialized for returning a long long from a (const) char*.
166  * @note is separate from the other signed types since a long long has a
167  * performance penalty at 32 bit systems.
168  */
169 template <class From>
171  long long
172  , From
173  , void
174  , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
175  char*, const char*> , From> >::type
176  >
177 {
178  long long operator()(From value)
179  {
180  DEBUG_THROW("specialized - To long long - From (const) char*");
181 
182  char* endptr;
183  int res = strtoll(value, &endptr, 10);
184 
185  if (*value == '\0' || *endptr != '\0') {
186  throw bad_lexical_cast();
187  } else {
188  return res;
189  }
190  }
191 };
192 
193 /**
194  * Specialized conversion class.
195  *
196  * Specialized for returning a long long from a std::string.
197  * @note is separate from the other signed types since a long long has a
198  * performance penalty at 32 bit systems.
199  */
200 template <>
202  long long
203  , std::string
204  >
205 {
206  long long operator()(const std::string& value)
207  {
208  DEBUG_THROW("specialized - To long long - From std::string");
209 
210  return lexical_cast<long long>(value.c_str());
211  }
212 };
213 
214 /**
215  * Specialized conversion class.
216  *
217  * Specialized for returning a signed type from a (const) char*.
218  */
219 template <class To, class From>
221  To
222  , From
223  , typename boost::enable_if<boost::is_signed<To> >::type
224  , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
225  char*, const char*> , From> >::type
226  >
227 {
228  To operator()(From value)
229  {
230  DEBUG_THROW("specialized - To signed - From (const) char*");
231 
232  char* endptr;
233  int res = strtol(value, &endptr, 10);
234 
235  if (*value == '\0' || *endptr != '\0') {
236  throw bad_lexical_cast();
237  } else {
238  return res;
239  }
240  }
241 };
242 
243 /**
244  * Specialized conversion class.
245  *
246  * Specialized for returning a signed type from a std::string.
247  */
248 template <class To>
250  To
251  , std::string
252  , typename boost::enable_if<boost::is_signed<To> >::type
253  >
254 {
256  {
257  DEBUG_THROW("specialized - To signed - From std::string");
258 
259  return lexical_cast<To>(value.c_str());
260  }
261 };
262 
263 /**
264  * Specialized conversion class.
265  *
266  * Specialized for returning a unsigned long long from a (const) char*.
267  * @note is separate from the other unsigned types since a unsigned long long
268  * has a performance penalty at 32 bit systems.
269  */
270 template <class From>
272  unsigned long long
273  , From
274  , void
275  , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
276  char*, const char*> , From> >::type
277  >
278 {
279  long long operator()(From value)
280  {
281  DEBUG_THROW(
282  "specialized - To unsigned long long - From (const) char*");
283 
284  char* endptr;
285  int res = strtoull(value, &endptr, 10);
286 
287  if (*value == '\0' || *endptr != '\0') {
288  throw bad_lexical_cast();
289  } else {
290  return res;
291  }
292  }
293 };
294 
295 /**
296  * Specialized conversion class.
297  *
298  * Specialized for returning a unsigned long long from a std::string.
299  * @note is separate from the other unsigned types since a unsigned long long
300  * has a performance penalty at 32 bit systems.
301  */
302 template <>
304  unsigned long long
305  , std::string
306  >
307 {
308  long long operator()(const std::string& value)
309  {
310  DEBUG_THROW("specialized - To unsigned long long - From std::string");
311 
312  return lexical_cast<unsigned long long>(value.c_str());
313  }
314 };
315 
316 /**
317  * Specialized conversion class.
318  *
319  * Specialized for returning a unsigned type from a (const) char*.
320  */
321 template <class To, class From>
323  To
324  , From
325  , typename boost::enable_if<boost::is_unsigned<To> >::type
326  , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
327  char*, const char*> , From> >::type
328  >
329 {
330  To operator()(From value)
331  {
332  DEBUG_THROW("specialized - To unsigned - From (const) char*");
333 
334  char* endptr;
335  int res = strtoul(value, &endptr, 10);
336 
337  if (*value == '\0' || *endptr != '\0') {
338  throw bad_lexical_cast();
339  } else {
340  return res;
341  }
342  }
343 };
344 
345 /**
346  * Specialized conversion class.
347  *
348  * Specialized for returning a unsigned type from a std::string.
349  */
350 template <class To>
352  To
353  , std::string
354  , typename boost::enable_if<boost::is_unsigned<To> >::type
355  >
356 {
358  {
359  DEBUG_THROW("specialized - To unsigned - From std::string");
360 
361  return lexical_cast<To>(value.c_str());
362  }
363 };
364 
365 } // namespace implementation
366 
367 #endif
368 
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1806
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
Base class for the conversion.
#define DEBUG_THROW(id)
Throws an exception for debugging.
STL namespace.
To lexical_cast(From value)
Lexical cast converts one type to another.
GLuint64EXT * result
Definition: glew.h:10727
GLsizei const GLfloat * value
Definition: glew.h:1817
long long operator()(const std::string &value)
GLuint res
Definition: glew.h:9258
Thrown when a lexical_cast fails.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
Contains the implementation details for lexical_cast and shouldn't be used directly.