Util: Add universal float parsing and formatting functions
Jeffrey Pfau jeffrey@endrift.com
Wed, 11 Feb 2015 00:19:55 -0800
6 files changed,
125 insertions(+),
31 deletions(-)
M
CMakeLists.txt
→
CMakeLists.txt
@@ -100,13 +100,6 @@ find_feature(USE_PNG "ZLIB;PNG")
find_feature(USE_LIBZIP "libzip") find_feature(USE_MAGICK "MagickWand") -include(CheckFunctionExists) -check_function_exists(strndup HAVE_STRNDUP) - -if(HAVE_STRNDUP) - add_definitions(-DHAVE_STRNDUP) -endif() - # Platform support if(WIN32) add_definitions(-D_WIN32_WINNT=0x0600)@@ -114,7 +107,7 @@ list(APPEND OS_LIB ws2_32)
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/windows/*.c) source_group("Windows-specific code" FILES ${OS_SRC}) else() - add_definitions(-DUSE_PTHREADS) + add_definitions(-DUSE_PTHREADS -D_GNU_SOURCE) list(APPEND OS_LIB pthread) file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/posix/*.c) source_group("POSIX-specific code" FILES ${OS_SRC})@@ -130,6 +123,29 @@ if(NOT BUILD_EGL)
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5) endif() endif() + +include(CheckFunctionExists) +check_function_exists(strndup HAVE_STRNDUP) +check_function_exists(snprintf_l HAVE_SNPRINTF_L) +check_function_exists(strtof_l HAVE_STRTOF_L) +check_function_exists(newlocale HAVE_NEWLOCALE) +check_function_exists(freelocale HAVE_FREELOCALE) +check_function_exists(uselocale HAVE_USELOCALE) + +if(HAVE_STRNDUP) + add_definitions(-DHAVE_STRNDUP) +endif() + +if(HAVE_NEWLOCALE AND HAVE_FREELOCALE AND HAVE_USELOCALE) + add_definitions(-DHAVE_LOCALE) + if (HAVE_STRTOF_L) + add_definitions(-DHAVE_STRTOF_L) + endif() + if (HAVE_SNPRINTF_L) + add_definitions(-DHAVE_SNPRINTF_L) + endif() +endif() + # Features set(DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/debugger.c ${CMAKE_SOURCE_DIR}/src/debugger/memory-debugger.c)
M
src/gba/supervisor/config.c
→
src/gba/supervisor/config.c
@@ -5,6 +5,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "config.h" +#include "util/formatting.h" + #include <sys/stat.h> #ifdef _WIN32@@ -85,15 +87,7 @@ if (!charValue) {
return false; } char* end; -#ifndef _WIN32 - locale_t l = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); - float value = strtof_l(charValue, &end, l); - freelocale(l); -#else - const char* oldlocale = setlocale(LC_NUMERIC, "C"); - float value = strtof(charValue, &end); - setlocale(LC_NUMERIC, oldlocale); -#endif + float value = strtof_u(charValue, &end); if (*end) { return false; }
M
src/util/common.h
→
src/util/common.h
@@ -10,7 +10,6 @@ #include <ctype.h>
#include <fcntl.h> #include <inttypes.h> #include <limits.h> -#include <locale.h> #include <math.h> #include <stdarg.h> #include <stdbool.h>@@ -20,10 +19,6 @@ #include <stdio.h>
#include <stdlib.h> #include <string.h> #include <unistd.h> - -#ifndef _WIN32 -#include <xlocale.h> -#endif #define UNUSED(V) (void)(V)
M
src/util/configuration.c
→
src/util/configuration.c
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "configuration.h" +#include "util/formatting.h" #include "util/vfs.h" #include "third-party/inih/ini.h"@@ -79,15 +80,7 @@ }
void ConfigurationSetFloatValue(struct Configuration* configuration, const char* section, const char* key, float value) { char charValue[16]; -#ifndef _WIN32 - locale_t l = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); - snprintf_l(charValue, sizeof(charValue), l, "%.*g", FLT_DIG, value); - freelocale(l); -#else - const char* oldlocale = setlocale(LC_NUMERIC, "C"); - snprintf(charValue, sizeof(charValue), "%.*g", FLT_DIG, value); - setlocale(LC_NUMERIC, oldlocale); -#endif + ftostr_u(charValue, sizeof(charValue), value); ConfigurationSetValue(configuration, section, key, charValue); }
A
src/util/formatting.c
@@ -0,0 +1,66 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "formatting.h" + +#include <float.h> + +int ftostr_l(char* restrict str, size_t size, float f, locale_t locale) { +#ifdef HAVE_SNPRINTF_L + return snprintf_l(str, size, locale, "%*.g", FLT_DIG, f); +#elif defined(HAVE_LOCALE) + locale_t old = uselocale(locale); + int res = snprintf(str, size, "%*.g", FLT_DIG, f); + uselocale(old); + return res; +#else + char* old = setlocale(LC_NUMERIC, locale); + int res = snprintf(str, size, "%*.g", FLT_DIG, f); + setlocale(LC_NUMERIC, old); + return res; +#endif +} + +#ifndef HAVE_STRTOF_L +float strtof_l(const char* restrict str, char** restrict end, locale_t locale) { +#ifdef HAVE_LOCALE + locale_t old = uselocale(locale); + float res = strtof(str, end); + uselocale(old); + return res; +#else + char* old = setlocale(LC_NUMERIC, locale); + float res = strtof(str, end); + setlocale(LC_NUMERIC, old); + return res; +#endif +} +#endif + +int ftostr_u(char* restrict str, size_t size, float f) { +#if HAVE_LOCALE + locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); +#else + locale_t l = "C"; +#endif + int res = ftostr_l(str, size, f, l); +#if HAVE_LOCALE + freelocale(l); +#endif + return res; +} + +float strtof_u(const char* restrict str, char** restrict end) { +#if HAVE_LOCALE + locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); +#else + locale_t l = "C"; +#endif + float res = strtof_l(str, end, l); +#if HAVE_LOCALE + freelocale(l); +#endif + return res; +}
A
src/util/formatting.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef FORMATTING_H +#define FORMATTING_H + +#include "util/common.h" + +#include "locale.h" + +#ifdef __APPLE__ +#include "xlocale.h" +#endif + +#ifndef HAVE_LOCALE +typedef const char* locale_t; +#endif + +int ftostr_l(char* restrict str, size_t size, float f, locale_t locale); + +#ifndef HAVE_STRTOF_L +float strtof_l(const char* restrict str, char** restrict end, locale_t locale); +#endif + +int ftostr_u(char* restrict str, size_t size, float f); +float strtof_u(const char* restrict str, char** restrict end); + +#endif