ProteoWizard
optimized_lexical_cast.hpp
Go to the documentation of this file.
1 //
2 // $Id$
3 //
4 //
5 // Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
6 //
7 // Copyright 2008 Spielberg Family Center for Applied Proteomics
8 // Cedars Sinai Medical Center, Los Angeles, California 90048
9 // Copyright 2008 Vanderbilt University - Nashville, TN 37232
10 //
11 // Licensed under the Apache License, Version 2.0 (the "License");
12 // you may not use this file except in compliance with the License.
13 // You may obtain a copy of the License at
14 //
15 // http://www.apache.org/licenses/LICENSE-2.0
16 //
17 // Unless required by applicable law or agreed to in writing, software
18 // distributed under the License is distributed on an "AS IS" BASIS,
19 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 // See the License for the specific language governing permissions and
21 // limitations under the License.
22 //
23 
24 #ifndef _OPTIMIZED_LEXICAL_CAST_HPP_
25 #define _OPTIMIZED_LEXICAL_CAST_HPP_
26 
27 #include <cstdlib>
28 #include <cerrno>
29 #include <boost/lexical_cast.hpp>
30 #include <boost/logic/tribool.hpp>
31 
32 
33 // HACK: Darwin strtod isn't threadsafe so strtod_l must be used
34 #ifdef __APPLE__
35 #include <xlocale.h>
37 
38 namespace {
39 
40 class ThreadSafeCLocale : public boost::singleton<ThreadSafeCLocale>
41 {
42  public:
43  ThreadSafeCLocale(boost::restricted) : c_locale(::newlocale(LC_ALL_MASK, "C", 0)) {}
44  ~ThreadSafeCLocale() {::freelocale(c_locale);}
45  ::locale_t c_locale;
46 };
47 
48 } // namespace
49 #define STRTOD(x, y) strtod_l((x), (y), ThreadSafeCLocale::instance->c_locale)
50 #define ATOF(x) STRTOD(x,NULL)
51 
52 #else // __APPLE__
53 #define STRTOD(x, y) strtod((x), (y))
54 #define ATOF(x) atof(x)
55 #endif // __APPLE__
56 
57 #define OPTIMIZED_LEXICAL_CAST(toType) \
58  template<> inline toType lexical_cast(const std::string& str) { \
59  bool success; \
60  toType value = lexical_cast<toType>(str, success); \
61  if (!success) \
62  throw bad_lexical_cast(); \
63  return value; \
64  }
65 
66 // optimized string->numeric conversions
67 namespace boost
68 {
69  template <typename toType>
70  inline toType lexical_cast(const std::string& str, bool& success)
71  {
72  // error: new overload needed below
73  throw std::logic_error("BUG: new overload needed");
74  }
75 
76  template <>
77  inline float lexical_cast( const std::string& str, bool& success )
78  {
79  errno = 0;
80  success = true;
81  const char* stringToConvert = str.c_str();
82  const char* endOfConversion = stringToConvert;
83  float value = (float) STRTOD( stringToConvert, const_cast<char**>(&endOfConversion) );
84  if( value == 0.0f && stringToConvert == endOfConversion ) // error: conversion could not be performed
85  success = false;
86  return value;
87  }
88 
90 
91  template <>
92  inline double lexical_cast( const std::string& str, bool& success )
93  {
94  errno = 0;
95  success = true;
96  const char* stringToConvert = str.c_str();
97  const char* endOfConversion = stringToConvert;
98  double value = STRTOD( stringToConvert, const_cast<char**>(&endOfConversion) );
99  if( value == 0.0 && stringToConvert == endOfConversion ) // error: conversion could not be performed
100  success = false;
101  return value;
102  }
103 
104  OPTIMIZED_LEXICAL_CAST(double)
105 
106  template <>
107  inline int lexical_cast( const std::string& str, bool& success )
108  {
109  errno = 0;
110  success = true;
111  const char* stringToConvert = str.c_str();
112  const char* endOfConversion = stringToConvert;
113  int value = (int) strtol( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
114  if( ( value == 0 && stringToConvert == endOfConversion ) || // error: conversion could not be performed
115  errno != 0 ) // error: overflow or underflow
116  success = false;
117  return value;
118  }
119 
121 
122  template <>
123  inline long lexical_cast( const std::string& str, bool& success )
124  {
125  errno = 0;
126  success = true;
127  const char* stringToConvert = str.c_str();
128  const char* endOfConversion = stringToConvert;
129  long value = strtol( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
130  if( ( value == 0l && stringToConvert == endOfConversion ) || // error: conversion could not be performed
131  errno != 0 ) // error: overflow or underflow
132  success = false;
133  return value;
134  }
135 
137 
138  template <>
139  inline unsigned int lexical_cast( const std::string& str, bool& success )
140  {
141  errno = 0;
142  success = true;
143  const char* stringToConvert = str.c_str();
144  const char* endOfConversion = stringToConvert;
145  unsigned int value = (unsigned int) strtoul( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
146  if( ( value == 0u && stringToConvert == endOfConversion ) || // error: conversion could not be performed
147  errno != 0 ) // error: overflow or underflow
148  success = false;
149  return value;
150  }
151 
152  OPTIMIZED_LEXICAL_CAST(unsigned int)
153 
154  template <>
155  inline unsigned long lexical_cast( const std::string& str, bool& success )
156  {
157  errno = 0;
158  success = true;
159  const char* stringToConvert = str.c_str();
160  const char* endOfConversion = stringToConvert;
161  unsigned long value = strtoul( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
162  if( ( value == 0ul && stringToConvert == endOfConversion ) || // error: conversion could not be performed
163  errno != 0 ) // error: overflow or underflow
164  success = false;
165  return value;
166  }
167 
168  OPTIMIZED_LEXICAL_CAST(unsigned long)
169 
170  template <>
171  inline long long lexical_cast( const std::string& str, bool& success )
172  {
173  errno = 0;
174  success = true;
175  const char* stringToConvert = str.c_str();
176  const char* endOfConversion = stringToConvert;
177  long long value = strtoll( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
178  if ((value == 0ll && stringToConvert == endOfConversion) || // error: conversion could not be performed
179  errno != 0 ) // error: overflow or underflow
180  success = false;
181  return value;
182  }
183 
184  OPTIMIZED_LEXICAL_CAST(long long)
185 
186  template <>
187  inline unsigned long long lexical_cast( const std::string& str, bool& success )
188  {
189  errno = 0;
190  success = true;
191  const char* stringToConvert = str.c_str();
192  const char* endOfConversion = stringToConvert;
193  unsigned long long value = strtoull( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
194  if( ( value == 0ull && stringToConvert == endOfConversion ) || // error: conversion could not be performed
195  errno != 0 ) // error: overflow or underflow
196  success = false;
197  return value;
198  }
199 
200  OPTIMIZED_LEXICAL_CAST(unsigned long long)
201 
202  template<>
203  inline bool lexical_cast( const std::string& str )
204  {
205  if (str == "0" || str == "false")
206  return false;
207  return true;
208  }
209 
210  template<>
211  inline boost::logic::tribool lexical_cast( const std::string& str )
212  {
213  using namespace boost::logic;
214  if (str.empty())
215  return tribool(indeterminate);
216  if (str == "0" || str == "false")
217  return false;
218  return true;
219  }
220 
221  /*template<>
222  inline float lexical_cast( const char*& str )
223  {
224  errno = 0;
225  const char* endOfConversion = str;
226  float value = (float) STRTOD( str, const_cast<char**>(&endOfConversion) );
227  if( ( value == 0.0f && str == endOfConversion ) || // error: conversion could not be performed
228  errno != 0 ) // error: overflow or underflow
229  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
230  return value;
231  }
232 
233  template<>
234  inline double lexical_cast( const char*& str )
235  {
236  errno = 0;
237  const char* endOfConversion = str;
238  double value = STRTOD( str, const_cast<char**>(&endOfConversion) );
239  if( ( value == 0.0 && str == endOfConversion ) || // error: conversion could not be performed
240  errno != 0 ) // error: overflow or underflow
241  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
242  return value;
243  }
244 
245  template<>
246  inline int lexical_cast( const char*& str )
247  {
248  errno = 0;
249  const char* endOfConversion = str;
250  int value = (int) strtol( str, const_cast<char**>(&endOfConversion), 0 );
251  if( ( value == 0 && str == endOfConversion ) || // error: conversion could not be performed
252  errno != 0 ) // error: overflow or underflow
253  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
254  return value;
255  }
256 
257  template<>
258  inline long lexical_cast( const char*& str )
259  {
260  errno = 0;
261  const char* endOfConversion = str;
262  long value = strtol( str, const_cast<char**>(&endOfConversion), 0 );
263  if( ( value == 0l && str == endOfConversion ) || // error: conversion could not be performed
264  errno != 0 ) // error: overflow or underflow
265  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
266  return value;
267  }
268 
269  template<>
270  inline unsigned int lexical_cast( const char*& str )
271  {
272  errno = 0;
273  const char* endOfConversion = str;
274  unsigned int value = (unsigned int) strtoul( str, const_cast<char**>(&endOfConversion), 0 );
275  if( ( value == 0u && str == endOfConversion ) || // error: conversion could not be performed
276  errno != 0 ) // error: overflow or underflow
277  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
278  return value;
279  }
280 
281  template<>
282  inline unsigned long lexical_cast( const char*& str )
283  {
284  errno = 0;
285  const char* endOfConversion = str;
286  unsigned long value = strtoul( str, const_cast<char**>(&endOfConversion), 0 );
287  if( ( value == 0ul && stringToConvert == endOfConversion ) || // error: conversion could not be performed
288  errno != 0 ) // error: overflow or underflow
289  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
290  return value;
291  }
292  */
293 } // boost
294 
295 #endif // _OPTIMIZED_LEXICAL_CAST_HPP_
#define OPTIMIZED_LEXICAL_CAST(toType)
boost::logic::tribool lexical_cast(const std::string &str)
#define STRTOD(x, y)
PWIZ_API_DECL std::string value(const std::string &id, const std::string &name)
convenience function to extract a named value from an id string