From 0cfde61dde5c547d303a725feb9a1e218ec7dc21 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Sun, 7 Oct 2018 14:56:18 +0300 Subject: [PATCH] A slow-but-working trick for proper local decimal separator handling --- .../c/simulation/simulation_info_json.c | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/SimulationRuntime/c/simulation/simulation_info_json.c b/SimulationRuntime/c/simulation/simulation_info_json.c index 21e8bc7dfe..91035f9a77 100644 --- a/SimulationRuntime/c/simulation/simulation_info_json.c +++ b/SimulationRuntime/c/simulation/simulation_info_json.c @@ -38,6 +38,10 @@ #include "util/omc_mmap.h" #include "solver/model_help.h" +#include + +#define MAX_DOUBLE_LEN 100 + static inline const char* skipSpace(const char* str) { do { @@ -53,6 +57,37 @@ static inline const char* skipSpace(const char* str) } while (1); } +static double strtod_c(const char *nptr, char **endptr) +{ + char loc_decimal_point = *localeconv()->decimal_point; + if (loc_decimal_point == '.') { + return strtod(nptr, endptr); + } + + char buf[MAX_DOUBLE_LEN + 1]; + strncpy(buf, nptr, MAX_DOUBLE_LEN); + + // In case of integer number: [2, ...] -> [2] with ',' as a decimal separator + char *loc_decimal_point_in_buf = strchr(buf, loc_decimal_point); + if (loc_decimal_point_in_buf) { + *loc_decimal_point_in_buf = '\0'; + } + + // In case of real number: [2.1, ...] -> [2.1] -> [2,1] + char *point_in_buf = strchr(buf, '.'); + if (point_in_buf) { + *point_in_buf = loc_decimal_point; + } + + // Perform actual parsing + char *end; + double res = strtod(buf, &end); + if (endptr) { + *endptr = (char *)(nptr + (end - buf)); + } + return res; +} + static const char* skipValue(const char* str); static inline const char* skipObjectRest(const char* str, int first) @@ -135,7 +170,7 @@ static const char* skipValue(const char* str) case '9': { char *endptr = NULL; - strtod(str,&endptr); + strtod_c(str,&endptr); if (str == endptr) { fprintf(stderr, "Not a number, got %.20s\n", str); abort(); @@ -175,7 +210,7 @@ static inline const char* assertNumber(const char *str, double expected) char *endptr = NULL; double d; str = skipSpace(str); - d = strtod(str, &endptr); + d = strtod_c(str, &endptr); if (str == endptr) { fprintf(stderr, "Expected number, got: %.20s\n", str); abort();