1// SExp - A S-Expression Parser for C++
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3// 2018 Ingo Ruhnke <grumbel@gmail.com>
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18#include "float.hpp"
19
20#ifdef SEXP_USE_CXX17
21# include <charconv>
22# include <assert.h>
23#endif
24
25#include <limits>
26#include <sstream>
27
28namespace sexp {
29
30float string2float(const std::string& text)
31{
32#ifdef SEXP_USE_CXX17
33 float result;
34 std::from_chars(text.data(), text.data() + text.size(), result);
35 return result;
36#else
37# ifdef SEXP_USE_LOCALE
38 std::istringstream in(text);
39 in.imbue(std::locale::classic());
40
41 float value;
42 in >> value;
43
44 return value;
45# else
46 return strtof(text.c_str(), nullptr);
47# endif
48#endif
49}
50
51void float2string(std::ostream& os, float value)
52{
53#ifdef SEXP_USE_CXX17
54 constexpr size_t len = std::numeric_limits<float>::digits10 + 1;
55 char buffer[len];
56 auto result = std::to_chars(buffer, buffer + len, value);
57 assert(result.ec == std::errc());
58 os.write(buffer, result.ptr - buffer);
59#else
60 auto precision = os.precision(std::numeric_limits<float>::digits10 + 1);
61# ifdef SEXP_USE_LOCALE
62 const auto& loc = os.getloc();
63 os.imbue(std::locale::classic());
64 os << value;
65 os.imbue(loc);
66# else
67 os << value;
68# endif
69 os.precision(precision);
70#endif
71}
72
73} // namespace sexp
74
75/* EOF */
76