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
38namespace {
39
40class 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
67namespace 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
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_
toType lexical_cast(const std::string &str, bool &success)
#define STRTOD(x, y)
#define OPTIMIZED_LEXICAL_CAST(toType)