2 Copyright (C) 2015 Tim Mayberry
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/string_convert.h"
22 #ifndef __STDC_FORMAT_MACROS
23 #define __STDC_FORMAT_MACROS
31 #include <glib/gprintf.h>
33 #include "pbd/compose.h"
34 #include "pbd/debug.h"
37 #define DEBUG_SCONVERT(msg) DEBUG_TRACE (PBD::DEBUG::StringConvert, string_compose ("%1: %2\n", __LINE__, msg));
39 #define CONVERT_BUF_SIZE 32
43 bool string_to_bool (const std::string& str, bool& val)
48 } else if (str == X_("1")) {
52 } else if (str == X_("0")) {
56 } else if (str == X_("y")) {
60 } else if (str == X_("n")) {
64 } else if (g_ascii_strncasecmp (str.c_str(), X_("yes"), str.length()) == 0) {
68 } else if (g_ascii_strncasecmp (str.c_str(), X_("no"), str.length()) == 0) {
72 } else if (g_ascii_strncasecmp (str.c_str(), X_("true"), str.length()) == 0) {
76 } else if (g_ascii_strncasecmp (str.c_str(), X_("false"), str.length()) == 0) {
82 string_compose ("string_to_bool conversion failed for %1", str));
87 bool string_to_int16 (const std::string& str, int16_t& val)
89 if (sscanf (str.c_str (), "%" SCNi16, &val) != 1) {
91 string_compose ("string_to_int16 conversion failed for %1", str));
97 bool string_to_uint16 (const std::string& str, uint16_t& val)
99 if (sscanf (str.c_str (), "%" SCNu16, &val) != 1) {
101 string_compose ("string_to_uint16 conversion failed for %1", str));
107 bool string_to_int32 (const std::string& str, int32_t& val)
109 if (sscanf (str.c_str (), "%" SCNi32, &val) != 1) {
111 string_compose ("string_to_int32 conversion failed for %1", str));
117 bool string_to_uint32 (const std::string& str, uint32_t& val)
119 if (sscanf (str.c_str (), "%" SCNu32, &val) != 1) {
121 string_compose ("string_to_uint32 conversion failed for %1", str));
127 bool string_to_int64 (const std::string& str, int64_t& val)
129 if (sscanf (str.c_str (), "%" SCNi64, &val) != 1) {
131 string_compose ("string_to_int64 conversion failed for %1", str));
137 bool string_to_uint64 (const std::string& str, uint64_t& val)
139 if (sscanf (str.c_str (), "%" SCNu64, &val) != 1) {
141 string_compose ("string_to_uint64 conversion failed for %1", str));
147 template <class FloatType>
149 _string_to_infinity (const std::string& str, FloatType& val)
151 if (!g_ascii_strncasecmp (str.c_str (), X_ ("inf"), str.length ()) ||
152 !g_ascii_strncasecmp (str.c_str (), X_ ("+inf"), str.length ()) ||
153 !g_ascii_strncasecmp (str.c_str (), X_ ("INFINITY"), str.length ()) ||
154 !g_ascii_strncasecmp (str.c_str (), X_ ("+INFINITY"), str.length ())) {
155 val = std::numeric_limits<FloatType>::infinity ();
157 } else if (!g_ascii_strncasecmp (str.c_str (), X_ ("-inf"), str.length ()) ||
158 !g_ascii_strncasecmp (str.c_str (), X_ ("-INFINITY"), str.length ())) {
159 val = -std::numeric_limits<FloatType>::infinity ();
166 _string_to_double (const std::string& str, double& val)
168 val = g_ascii_strtod (str.c_str (), NULL);
170 // It is possible that the conversion was successful and another thread
171 // has set errno meanwhile but as most conversions are currently not
172 // checked for error conditions this is better than nothing.
173 if (errno == ERANGE) {
174 DEBUG_SCONVERT (string_compose ("string_to_double possible conversion failure for %1", str));
175 // There should not be any conversion failures as we control the string
176 // contents so returning false here should not have any impact...
182 bool string_to_float (const std::string& str, float& val)
185 if (_string_to_double (str, tmp)) {
190 if (_string_to_infinity (str, val)) {
197 bool string_to_double (const std::string& str, double& val)
199 if (_string_to_double (str, val)) {
203 if (_string_to_infinity (str, val)) {
210 bool bool_to_string (bool val, std::string& str)
220 bool int16_to_string (int16_t val, std::string& str)
222 char buffer[CONVERT_BUF_SIZE];
224 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIi16, val);
226 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
228 string_compose ("int16_to_string conversion failure for %1", val));
235 bool uint16_to_string (uint16_t val, std::string& str)
237 char buffer[CONVERT_BUF_SIZE];
239 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIu16, val);
241 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
243 string_compose ("uint16_to_string conversion failure for %1", val));
250 bool int32_to_string (int32_t val, std::string& str)
252 char buffer[CONVERT_BUF_SIZE];
254 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIi32, val);
256 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
258 string_compose ("int32_to_string conversion failure for %1", val));
265 bool uint32_to_string (uint32_t val, std::string& str)
267 char buffer[CONVERT_BUF_SIZE];
269 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIu32, val);
271 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
273 string_compose ("uint32_to_string conversion failure for %1", val));
280 bool int64_to_string (int64_t val, std::string& str)
282 char buffer[CONVERT_BUF_SIZE];
284 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIi64, val);
286 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
288 string_compose ("int64_to_string conversion failure for %1", val));
295 bool uint64_to_string (uint64_t val, std::string& str)
297 char buffer[CONVERT_BUF_SIZE];
299 int retval = g_snprintf (buffer, sizeof(buffer), "%" PRIu64, val);
301 if (retval <= 0 || retval >= (int)sizeof(buffer)) {
303 string_compose ("uint64_to_string conversion failure for %1", val));
310 template <class FloatType>
312 _infinity_to_string (FloatType val, std::string& str)
314 if (val == std::numeric_limits<FloatType>::infinity ()) {
317 } else if (val == -std::numeric_limits<FloatType>::infinity ()) {
325 _double_to_string (double val, std::string& str)
327 char buffer[G_ASCII_DTOSTR_BUF_SIZE];
329 char* d_cstr = g_ascii_dtostr (buffer, sizeof(buffer), val);
331 if (d_cstr == NULL) {
338 bool float_to_string (float val, std::string& str)
340 if (_infinity_to_string (val, str)) {
344 if (_double_to_string (val, str)) {
348 DEBUG_SCONVERT (string_compose ("float_to_string conversion failure for %1", val));
352 bool double_to_string (double val, std::string& str)
354 if (_infinity_to_string (val, str)) {
358 if (_double_to_string (val, str)) {
362 DEBUG_SCONVERT (string_compose ("double_to_string conversion failure for %1", val));