ProteoWizard
optimized_lexical_cast.hpp
Go to the documentation of this file.
1 //
2 // $Id: optimized_lexical_cast.hpp 3126 2011-11-15 21:14:55Z chambm $
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 
58 // optimized string->numeric conversions
59 namespace boost
60 {
61  template<>
62  inline float lexical_cast( const std::string& str )
63  {
64  errno = 0;
65  const char* stringToConvert = str.c_str();
66  const char* endOfConversion = stringToConvert;
67  float value = (float) STRTOD( stringToConvert, const_cast<char**>(&endOfConversion) );
68  if( value == 0.0f && stringToConvert == endOfConversion ) // error: conversion could not be performed
69  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
70  return value;
71  }
72 
73  template<>
74  inline double lexical_cast( const std::string& str )
75  {
76  errno = 0;
77  const char* stringToConvert = str.c_str();
78  const char* endOfConversion = stringToConvert;
79  double value = STRTOD( stringToConvert, const_cast<char**>(&endOfConversion) );
80  if( value == 0.0 && stringToConvert == endOfConversion ) // error: conversion could not be performed
81  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
82  return value;
83  }
84 
85  template<>
86  inline int lexical_cast( const std::string& str )
87  {
88  errno = 0;
89  const char* stringToConvert = str.c_str();
90  const char* endOfConversion = stringToConvert;
91  int value = (int) strtol( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
92  if( ( value == 0 && stringToConvert == endOfConversion ) || // error: conversion could not be performed
93  errno != 0 ) // error: overflow or underflow
94  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
95  return value;
96  }
97 
98  template<>
99  inline long lexical_cast( const std::string& str )
100  {
101  errno = 0;
102  const char* stringToConvert = str.c_str();
103  const char* endOfConversion = stringToConvert;
104  long value = strtol( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
105  if( ( value == 0l && stringToConvert == endOfConversion ) || // error: conversion could not be performed
106  errno != 0 ) // error: overflow or underflow
107  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
108  return value;
109  }
110 
111  template<>
112  inline unsigned int lexical_cast( const std::string& str )
113  {
114  errno = 0;
115  const char* stringToConvert = str.c_str();
116  const char* endOfConversion = stringToConvert;
117  unsigned int value = (unsigned int) strtoul( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
118  if( ( value == 0u && stringToConvert == endOfConversion ) || // error: conversion could not be performed
119  errno != 0 ) // error: overflow or underflow
120  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
121  return value;
122  }
123 
124  template<>
125  inline unsigned long lexical_cast( const std::string& str )
126  {
127  errno = 0;
128  const char* stringToConvert = str.c_str();
129  const char* endOfConversion = stringToConvert;
130  unsigned long value = strtoul( stringToConvert, const_cast<char**>(&endOfConversion), 0 );
131  if( ( value == 0ul && stringToConvert == endOfConversion ) || // error: conversion could not be performed
132  errno != 0 ) // error: overflow or underflow
133  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
134  return value;
135  }
136 
137  template<>
138  inline bool lexical_cast( const std::string& str )
139  {
140  if (str == "0" || str == "false")
141  return false;
142  return true;
143  }
144 
145  template<>
146  inline boost::logic::tribool lexical_cast( const std::string& str )
147  {
148  using namespace boost::logic;
149  if (str.empty())
150  return tribool(indeterminate);
151  if (str == "0" || str == "false")
152  return false;
153  return true;
154  }
155 
156  /*template<>
157  inline float lexical_cast( const char*& str )
158  {
159  errno = 0;
160  const char* endOfConversion = str;
161  float value = (float) STRTOD( str, const_cast<char**>(&endOfConversion) );
162  if( ( value == 0.0f && str == endOfConversion ) || // error: conversion could not be performed
163  errno != 0 ) // error: overflow or underflow
164  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
165  return value;
166  }
167 
168  template<>
169  inline double lexical_cast( const char*& str )
170  {
171  errno = 0;
172  const char* endOfConversion = str;
173  double value = STRTOD( str, const_cast<char**>(&endOfConversion) );
174  if( ( value == 0.0 && str == endOfConversion ) || // error: conversion could not be performed
175  errno != 0 ) // error: overflow or underflow
176  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
177  return value;
178  }
179 
180  template<>
181  inline int lexical_cast( const char*& str )
182  {
183  errno = 0;
184  const char* endOfConversion = str;
185  int value = (int) strtol( str, const_cast<char**>(&endOfConversion), 0 );
186  if( ( value == 0 && str == endOfConversion ) || // error: conversion could not be performed
187  errno != 0 ) // error: overflow or underflow
188  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
189  return value;
190  }
191 
192  template<>
193  inline long lexical_cast( const char*& str )
194  {
195  errno = 0;
196  const char* endOfConversion = str;
197  long value = strtol( str, const_cast<char**>(&endOfConversion), 0 );
198  if( ( value == 0l && str == endOfConversion ) || // error: conversion could not be performed
199  errno != 0 ) // error: overflow or underflow
200  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
201  return value;
202  }
203 
204  template<>
205  inline unsigned int lexical_cast( const char*& str )
206  {
207  errno = 0;
208  const char* endOfConversion = str;
209  unsigned int value = (unsigned int) strtoul( str, const_cast<char**>(&endOfConversion), 0 );
210  if( ( value == 0u && str == endOfConversion ) || // error: conversion could not be performed
211  errno != 0 ) // error: overflow or underflow
212  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
213  return value;
214  }
215 
216  template<>
217  inline unsigned long lexical_cast( const char*& str )
218  {
219  errno = 0;
220  const char* endOfConversion = str;
221  unsigned long value = strtoul( str, const_cast<char**>(&endOfConversion), 0 );
222  if( ( value == 0ul && stringToConvert == endOfConversion ) || // error: conversion could not be performed
223  errno != 0 ) // error: overflow or underflow
224  throw bad_lexical_cast();//throw bad_lexical_cast( std::type_info( str ), std::type_info( value ) );
225  return value;
226  }
227  */
228 } // boost
229 
230 #endif // _OPTIMIZED_LEXICAL_CAST_HPP_