Util: Add universal float parsing and formatting functions

This commit is contained in:
Jeffrey Pfau 2015-02-11 00:19:55 -08:00
parent f2c29bc8d6
commit 1e71f62a3c
6 changed files with 125 additions and 31 deletions

View File

@ -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")

View File

@ -5,6 +5,8 @@
* 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 @@ 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;
}

View File

@ -10,7 +10,6 @@
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
@ -21,10 +20,6 @@
#include <string.h>
#include <unistd.h>
#ifndef _WIN32
#include <xlocale.h>
#endif
#define UNUSED(V) (void)(V)
#endif

View File

@ -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);
}

66
src/util/formatting.c Normal file
View File

@ -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;
}

30
src/util/formatting.h Normal file
View File

@ -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