From 1e71f62a3c031325809005c9f1c720ccd30d0df5 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Wed, 11 Feb 2015 00:19:55 -0800 Subject: [PATCH] Util: Add universal float parsing and formatting functions --- CMakeLists.txt | 32 +++++++++++++----- src/gba/supervisor/config.c | 12 ++----- src/util/common.h | 5 --- src/util/configuration.c | 11 ++----- src/util/formatting.c | 66 +++++++++++++++++++++++++++++++++++++ src/util/formatting.h | 30 +++++++++++++++++ 6 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 src/util/formatting.c create mode 100644 src/util/formatting.h diff --git a/CMakeLists.txt b/CMakeLists.txt index af2fc0674..19c67e030 100644 --- a/CMakeLists.txt +++ b/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 @@ if(WIN32) 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}) @@ -131,6 +124,29 @@ if(BUILD_BBB OR BUILD_RASPI) 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) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6") diff --git a/src/gba/supervisor/config.c b/src/gba/supervisor/config.c index c45c004c6..c101b20f8 100644 --- a/src/gba/supervisor/config.c +++ b/src/gba/supervisor/config.c @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "config.h" +#include "util/formatting.h" + #include #ifdef _WIN32 @@ -85,15 +87,7 @@ static bool _lookupFloatValue(const struct GBAConfig* config, const char* key, f 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; } diff --git a/src/util/common.h b/src/util/common.h index 1dd43ef3f..42f62c05f 100644 --- a/src/util/common.h +++ b/src/util/common.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -21,10 +20,6 @@ #include #include -#ifndef _WIN32 -#include -#endif - #define UNUSED(V) (void)(V) #endif diff --git a/src/util/configuration.c b/src/util/configuration.c index 86226b61c..f087aec82 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -5,6 +5,7 @@ * 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 ConfigurationSetUIntValue(struct Configuration* configuration, const char* 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); } diff --git a/src/util/formatting.c b/src/util/formatting.c new file mode 100644 index 000000000..a2d572781 --- /dev/null +++ b/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 + +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; +} diff --git a/src/util/formatting.h b/src/util/formatting.h new file mode 100644 index 000000000..1ea621dc0 --- /dev/null +++ b/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