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