From 009c6e8e26585f6fe1637f4868074984153e4f16 Mon Sep 17 00:00:00 2001 From: paszqa Date: Tue, 2 Sep 2025 17:15:10 +0200 Subject: [PATCH 1/4] Fixed locale-dependent parsing of decimal values in time, best_time and best_segment. --- src/main.c | 1 + src/timer.c | 57 ++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index b9b8eee..0020218 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include "bind.h" #include "component/components.h" #include "main.h" +#include "main_css.h" #include "settings.h" #include "timer.h" diff --git a/src/timer.c b/src/timer.c index 943888f..f9b8e29 100644 --- a/src/timer.c +++ b/src/timer.c @@ -23,13 +23,32 @@ long long ls_time_value(const char* string) if (!string || !strlen(string)) { return 0; } - sscanf(string, "%[^.]%lf", seconds_part, &subseconds_part); - string = seconds_part; - if (string[0] == '-') { + + // Split at the decimal point manually + char* dot_pos = strchr(string, '.'); + if (dot_pos) { + strncpy(seconds_part, string, dot_pos - string); + seconds_part[dot_pos - string] = '\0'; + + // Manually parse the fractional part to avoid locale issues + char* frac_part = dot_pos + 1; + subseconds_part = 0.0; + double multiplier = 0.1; + + for (char* p = frac_part; *p && *p >= '0' && *p <= '9'; p++) { + subseconds_part += (*p - '0') * multiplier; + multiplier *= 0.1; + } + } else { + strcpy(seconds_part, string); + subseconds_part = 0.0; + } + + if (seconds_part[0] == '-') { sign = -1; - ++string; + memmove(seconds_part, seconds_part + 1, strlen(seconds_part)); } - switch (sscanf(string, "%d:%d:%d", &hours, &minutes, &seconds)) { + switch (sscanf(seconds_part, "%d:%d:%d", &hours, &minutes, &seconds)) { case 2: seconds = minutes; minutes = hours; @@ -41,7 +60,8 @@ long long ls_time_value(const char* string) hours = 0; break; } - return sign * ((hours * 60 * 60 + minutes * 60 + seconds) * 1000000LL + (int)(subseconds_part * 1000000.)); + + return sign * ((hours * 60 * 60 + minutes * 60 + seconds) * 1000000LL + (long long)(subseconds_part * 1000000.)); } static void ls_time_string_format(char* string, @@ -398,12 +418,25 @@ int ls_game_save(const ls_game* game) json_t* split = json_object(); json_object_set_new(split, "title", json_string(game->split_titles[i])); - ls_time_string_serialized(str, game->split_times[i]); - json_object_set_new(split, "time", json_string(str)); - ls_time_string_serialized(str, game->best_splits[i]); - json_object_set_new(split, "best_time", json_string(str)); - ls_time_string_serialized(str, game->best_segments[i]); - json_object_set_new(split, "best_segment", json_string(str)); + + // Only save "time" if it's not zero + if (game->split_times[i] != 0) { + ls_time_string_serialized(str, game->split_times[i]); + json_object_set_new(split, "time", json_string(str)); + } + + // Only save "best_time" if it's not zero + if (game->best_splits[i] != 0) { + ls_time_string_serialized(str, game->best_splits[i]); + json_object_set_new(split, "best_time", json_string(str)); + } + + // Only save "best_segment" if it's not zero + if (game->best_segments[i] != 0) { + ls_time_string_serialized(str, game->best_segments[i]); + json_object_set_new(split, "best_segment", json_string(str)); + } + json_array_append_new(splits, split); } json_object_set_new(json, "splits", splits); From 6684d5d654129c236e90ed757ae279c480528972 Mon Sep 17 00:00:00 2001 From: paszqa Date: Tue, 2 Sep 2025 17:20:26 +0200 Subject: [PATCH 2/4] Fixed locate-dependent decimal parsing in split file values --- src/timer.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/timer.c b/src/timer.c index f9b8e29..a120ce9 100644 --- a/src/timer.c +++ b/src/timer.c @@ -23,18 +23,18 @@ long long ls_time_value(const char* string) if (!string || !strlen(string)) { return 0; } - + // Split at the decimal point manually char* dot_pos = strchr(string, '.'); if (dot_pos) { strncpy(seconds_part, string, dot_pos - string); seconds_part[dot_pos - string] = '\0'; - + // Manually parse the fractional part to avoid locale issues char* frac_part = dot_pos + 1; subseconds_part = 0.0; double multiplier = 0.1; - + for (char* p = frac_part; *p && *p >= '0' && *p <= '9'; p++) { subseconds_part += (*p - '0') * multiplier; multiplier *= 0.1; @@ -43,7 +43,7 @@ long long ls_time_value(const char* string) strcpy(seconds_part, string); subseconds_part = 0.0; } - + if (seconds_part[0] == '-') { sign = -1; memmove(seconds_part, seconds_part + 1, strlen(seconds_part)); @@ -60,7 +60,7 @@ long long ls_time_value(const char* string) hours = 0; break; } - + return sign * ((hours * 60 * 60 + minutes * 60 + seconds) * 1000000LL + (long long)(subseconds_part * 1000000.)); } @@ -418,25 +418,25 @@ int ls_game_save(const ls_game* game) json_t* split = json_object(); json_object_set_new(split, "title", json_string(game->split_titles[i])); - + // Only save "time" if it's not zero if (game->split_times[i] != 0) { ls_time_string_serialized(str, game->split_times[i]); json_object_set_new(split, "time", json_string(str)); } - + // Only save "best_time" if it's not zero if (game->best_splits[i] != 0) { ls_time_string_serialized(str, game->best_splits[i]); json_object_set_new(split, "best_time", json_string(str)); } - + // Only save "best_segment" if it's not zero if (game->best_segments[i] != 0) { ls_time_string_serialized(str, game->best_segments[i]); json_object_set_new(split, "best_segment", json_string(str)); } - + json_array_append_new(splits, split); } json_object_set_new(json, "splits", splits); From ecf61a90f27c8b13d72c744e00304183fbd86b1c Mon Sep 17 00:00:00 2001 From: paszqa Date: Tue, 2 Sep 2025 17:27:03 +0200 Subject: [PATCH 3/4] Fix locale-dependent decimal parsing in time values. --- src/timer.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/timer.c b/src/timer.c index a120ce9..f9b8e29 100644 --- a/src/timer.c +++ b/src/timer.c @@ -23,18 +23,18 @@ long long ls_time_value(const char* string) if (!string || !strlen(string)) { return 0; } - + // Split at the decimal point manually char* dot_pos = strchr(string, '.'); if (dot_pos) { strncpy(seconds_part, string, dot_pos - string); seconds_part[dot_pos - string] = '\0'; - + // Manually parse the fractional part to avoid locale issues char* frac_part = dot_pos + 1; subseconds_part = 0.0; double multiplier = 0.1; - + for (char* p = frac_part; *p && *p >= '0' && *p <= '9'; p++) { subseconds_part += (*p - '0') * multiplier; multiplier *= 0.1; @@ -43,7 +43,7 @@ long long ls_time_value(const char* string) strcpy(seconds_part, string); subseconds_part = 0.0; } - + if (seconds_part[0] == '-') { sign = -1; memmove(seconds_part, seconds_part + 1, strlen(seconds_part)); @@ -60,7 +60,7 @@ long long ls_time_value(const char* string) hours = 0; break; } - + return sign * ((hours * 60 * 60 + minutes * 60 + seconds) * 1000000LL + (long long)(subseconds_part * 1000000.)); } @@ -418,25 +418,25 @@ int ls_game_save(const ls_game* game) json_t* split = json_object(); json_object_set_new(split, "title", json_string(game->split_titles[i])); - + // Only save "time" if it's not zero if (game->split_times[i] != 0) { ls_time_string_serialized(str, game->split_times[i]); json_object_set_new(split, "time", json_string(str)); } - + // Only save "best_time" if it's not zero if (game->best_splits[i] != 0) { ls_time_string_serialized(str, game->best_splits[i]); json_object_set_new(split, "best_time", json_string(str)); } - + // Only save "best_segment" if it's not zero if (game->best_segments[i] != 0) { ls_time_string_serialized(str, game->best_segments[i]); json_object_set_new(split, "best_segment", json_string(str)); } - + json_array_append_new(splits, split); } json_object_set_new(json, "splits", splits); From 1a45d50d2c429d247aaf3a79484473b78b8acdf2 Mon Sep 17 00:00:00 2001 From: paszqa Date: Tue, 2 Sep 2025 17:27:42 +0200 Subject: [PATCH 4/4] Fix locale-dependent decimal parsing in time values. --- src/timer.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/timer.c b/src/timer.c index f9b8e29..a120ce9 100644 --- a/src/timer.c +++ b/src/timer.c @@ -23,18 +23,18 @@ long long ls_time_value(const char* string) if (!string || !strlen(string)) { return 0; } - + // Split at the decimal point manually char* dot_pos = strchr(string, '.'); if (dot_pos) { strncpy(seconds_part, string, dot_pos - string); seconds_part[dot_pos - string] = '\0'; - + // Manually parse the fractional part to avoid locale issues char* frac_part = dot_pos + 1; subseconds_part = 0.0; double multiplier = 0.1; - + for (char* p = frac_part; *p && *p >= '0' && *p <= '9'; p++) { subseconds_part += (*p - '0') * multiplier; multiplier *= 0.1; @@ -43,7 +43,7 @@ long long ls_time_value(const char* string) strcpy(seconds_part, string); subseconds_part = 0.0; } - + if (seconds_part[0] == '-') { sign = -1; memmove(seconds_part, seconds_part + 1, strlen(seconds_part)); @@ -60,7 +60,7 @@ long long ls_time_value(const char* string) hours = 0; break; } - + return sign * ((hours * 60 * 60 + minutes * 60 + seconds) * 1000000LL + (long long)(subseconds_part * 1000000.)); } @@ -418,25 +418,25 @@ int ls_game_save(const ls_game* game) json_t* split = json_object(); json_object_set_new(split, "title", json_string(game->split_titles[i])); - + // Only save "time" if it's not zero if (game->split_times[i] != 0) { ls_time_string_serialized(str, game->split_times[i]); json_object_set_new(split, "time", json_string(str)); } - + // Only save "best_time" if it's not zero if (game->best_splits[i] != 0) { ls_time_string_serialized(str, game->best_splits[i]); json_object_set_new(split, "best_time", json_string(str)); } - + // Only save "best_segment" if it's not zero if (game->best_segments[i] != 0) { ls_time_string_serialized(str, game->best_segments[i]); json_object_set_new(split, "best_segment", json_string(str)); } - + json_array_append_new(splits, split); } json_object_set_new(json, "splits", splits);