Warning, file /sdk/codevis/thirdparty/soci/include/private/soci-cstrtod.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // 0002 // Copyright (C) 2014 Vadim Zeitlin. 0003 // Distributed under the Boost Software License, Version 1.0. 0004 // (See accompanying file LICENSE_1_0.txt or copy at 0005 // http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 0008 #ifndef SOCI_PRIVATE_SOCI_CSTRTOD_H_INCLUDED 0009 #define SOCI_PRIVATE_SOCI_CSTRTOD_H_INCLUDED 0010 0011 #include "soci/error.h" 0012 0013 #include <stdlib.h> 0014 #include <string.h> 0015 0016 namespace soci 0017 { 0018 0019 namespace details 0020 { 0021 0022 // Locale-independent, i.e. always using "C" locale, function for converting 0023 // strings to numbers. 0024 // 0025 // The string must contain a floating point number in "C" locale, i.e. using 0026 // point as decimal separator, and nothing but it. If it does, the converted 0027 // number is returned, otherwise an exception is thrown. 0028 inline 0029 double cstring_to_double(char const* s) 0030 { 0031 // Unfortunately there is no clean way to parse a number in C locale 0032 // without this hack: normally, using std::istringstream with classic 0033 // locale should work, but some standard library implementations are buggy 0034 // and handle non-default locale in thread-unsafe way, by changing the 0035 // global C locale which is unacceptable as it introduces subtle bugs in 0036 // multi-thread programs. So we rely on just the standard C functions and 0037 // try to make them work by tweaking the input into the form appropriate 0038 // for the current locale. 0039 0040 // First try with the original input. 0041 char* end; 0042 double d = strtod(s, &end); 0043 0044 bool parsedOK; 0045 if (*end == '.') 0046 { 0047 // Parsing may have stopped because the current locale uses something 0048 // different from the point as decimal separator, retry with a comma. 0049 // 0050 // In principle, values other than point or comma are possible but they 0051 // don't seem to be used in practice, so for now keep things simple. 0052 size_t const bufSize = strlen(s) + 1; 0053 char* const buf = new char[bufSize]; 0054 strcpy(buf, s); 0055 buf[end - s] = ','; 0056 d = strtod(buf, &end); 0057 parsedOK = end != buf && *end == '\0'; 0058 delete [] buf; 0059 } 0060 else 0061 { 0062 // Notice that we must detect false positives as well: parsing a string 0063 // using decimal comma should fail when using this function. 0064 parsedOK = end != s && *end == '\0' && !strchr(s, ','); 0065 } 0066 0067 if (!parsedOK) 0068 { 0069 throw soci_error(std::string("Cannot convert data: string \"") + s + "\" " 0070 "is not a number."); 0071 } 0072 0073 return d; 0074 } 0075 0076 } // namespace details 0077 0078 } // namespace soci 0079 0080 #endif // SOCI_PRIVATE_SOCI_CSTRTOD_H_INCLUDED