From 9a0236b9e249f002accfb222a969be0c676115b7 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Thu, 6 Dec 2012 10:29:23 +0100 Subject: Changed reading and writing of floating point numbers into configuration files to make it independent of the decimal point used in the current locale --- CONTRIBUTORS | 2 ++ HISTORY | 18 +++++++++++++++++- config.c | 20 ++++++++++---------- recording.c | 6 +++--- tools.c | 28 +++++++++++++++++++++++++++- tools.h | 10 +++++++++- vdr.c | 3 +-- 7 files changed, 69 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index de1f6ed1..46a4c62b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3013,3 +3013,5 @@ Stefan Hofmann Stefan Blochberger for suggesting to automatically display the progress display whenever replay of a recording is started + for suggesting that floating point numbers presented to the user shall be displayed + in the way defined by the current locale diff --git a/HISTORY b/HISTORY index ee0515d1..c8dc570c 100644 --- a/HISTORY +++ b/HISTORY @@ -7339,7 +7339,7 @@ Video Disk Recorder Revision History - Modified editing marks are now written to disk whenever the replay progress display gets hidden (thanks to Christoph Haubrich). -2012-12-05: Version 1.7.33 +2012-12-06: Version 1.7.33 - In order to be able to play TS recordings from other sources, in which there is more than one PMT PID in the PAT, 'int cPatPmtParser::PatPmt(void)' has been changed @@ -7396,3 +7396,19 @@ Video Disk Recorder Revision History - The new option "Setup/Replay/Progress display time" can be used to activate automatically displaying the progress display whenever replay of a recording is started (suggested by Stefan Blochberger). +- Changed reading and writing of floating point numbers into configuration files to + make it independent of the decimal point used in the current locale. All calls to + atof() have been replaced with the new function atod(), which makes sure the string + representation of a floating point number using a '.' as decimal point will be + handled correctly, even if the locale in use expects a ',' as the decimal point. + Plugins that read floating point numbers from their own configuration files will + also need to use atod() for this, or use a method of their own (this is not necessary + if values are stored in VDR's setup.conf file, because VDR takes care of this). + The reason for these changes is that floating point numbers presented to the user + shall be displayed in the way defined by the current locale (suggested by Stefan + Blochberger). + If you use plugins that store floating point values in configuration files of their + own and have not yet been adapted to this change, you should set + export LC_NUMERIC=C + before running VDR. Otherwise your plugin's configuration data may not be read or + written correctly. diff --git a/config.c b/config.c index 12aab46e..af0fe3d5 100644 --- a/config.c +++ b/config.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 2.30 2012/12/05 11:33:14 kls Exp $ + * $Id: config.c 2.31 2012/12/06 09:00:23 kls Exp $ */ #include "config.h" @@ -509,7 +509,7 @@ void cSetup::Store(const char *Name, int Value, const char *Plugin) void cSetup::Store(const char *Name, double &Value, const char *Plugin) { - Store(Name, cString::sprintf("%f", Value), Plugin); + Store(Name, dtoa(Value), Plugin); } bool cSetup::Load(const char *FileName) @@ -630,24 +630,24 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "UseDolbyDigital")) UseDolbyDigital = atoi(Value); else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value); else if (!strcasecmp(Name, "ChannelInfoTime")) ChannelInfoTime = atoi(Value); - else if (!strcasecmp(Name, "OSDLeftP")) OSDLeftP = atof(Value); - else if (!strcasecmp(Name, "OSDTopP")) OSDTopP = atof(Value); - else if (!strcasecmp(Name, "OSDWidthP")) { OSDWidthP = atof(Value); ChkDoublePlausibility(OSDWidthP, 0.87); } - else if (!strcasecmp(Name, "OSDHeightP")) { OSDHeightP = atof(Value); ChkDoublePlausibility(OSDHeightP, 0.84); } + else if (!strcasecmp(Name, "OSDLeftP")) OSDLeftP = atod(Value); + else if (!strcasecmp(Name, "OSDTopP")) OSDTopP = atod(Value); + else if (!strcasecmp(Name, "OSDWidthP")) { OSDWidthP = atod(Value); ChkDoublePlausibility(OSDWidthP, 0.87); } + else if (!strcasecmp(Name, "OSDHeightP")) { OSDHeightP = atod(Value); ChkDoublePlausibility(OSDHeightP, 0.84); } else if (!strcasecmp(Name, "OSDLeft")) OSDLeft = atoi(Value); else if (!strcasecmp(Name, "OSDTop")) OSDTop = atoi(Value); else if (!strcasecmp(Name, "OSDWidth")) { OSDWidth = atoi(Value); OSDWidth &= ~0x07; } // OSD width must be a multiple of 8 else if (!strcasecmp(Name, "OSDHeight")) OSDHeight = atoi(Value); - else if (!strcasecmp(Name, "OSDAspect")) OSDAspect = atof(Value); + else if (!strcasecmp(Name, "OSDAspect")) OSDAspect = atod(Value); else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value); else if (!strcasecmp(Name, "UseSmallFont")) UseSmallFont = atoi(Value); else if (!strcasecmp(Name, "AntiAlias")) AntiAlias = atoi(Value); else if (!strcasecmp(Name, "FontOsd")) Utf8Strn0Cpy(FontOsd, Value, MAXFONTNAME); else if (!strcasecmp(Name, "FontSml")) Utf8Strn0Cpy(FontSml, Value, MAXFONTNAME); else if (!strcasecmp(Name, "FontFix")) Utf8Strn0Cpy(FontFix, Value, MAXFONTNAME); - else if (!strcasecmp(Name, "FontOsdSizeP")) { FontOsdSizeP = atof(Value); ChkDoublePlausibility(FontOsdSizeP, 0.038); } - else if (!strcasecmp(Name, "FontSmlSizeP")) { FontSmlSizeP = atof(Value); ChkDoublePlausibility(FontSmlSizeP, 0.035); } - else if (!strcasecmp(Name, "FontFixSizeP")) { FontFixSizeP = atof(Value); ChkDoublePlausibility(FontFixSizeP, 0.031); } + else if (!strcasecmp(Name, "FontOsdSizeP")) { FontOsdSizeP = atod(Value); ChkDoublePlausibility(FontOsdSizeP, 0.038); } + else if (!strcasecmp(Name, "FontSmlSizeP")) { FontSmlSizeP = atod(Value); ChkDoublePlausibility(FontSmlSizeP, 0.035); } + else if (!strcasecmp(Name, "FontFixSizeP")) { FontFixSizeP = atod(Value); ChkDoublePlausibility(FontFixSizeP, 0.031); } else if (!strcasecmp(Name, "FontOsdSize")) FontOsdSize = atoi(Value); else if (!strcasecmp(Name, "FontSmlSize")) FontSmlSize = atoi(Value); else if (!strcasecmp(Name, "FontFixSize")) FontFixSize = atoi(Value); diff --git a/recording.c b/recording.c index 00f95ca6..87ca8efe 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 2.77 2012/12/05 11:08:47 kls Exp $ + * $Id: recording.c 2.78 2012/12/06 09:35:13 kls Exp $ */ #include "recording.h" @@ -455,7 +455,7 @@ bool cRecordingInfo::Read(FILE *f) } } break; - case 'F': framesPerSecond = atof(t); + case 'F': framesPerSecond = atod(t); break; case 'L': lifetime = atoi(t); break; @@ -482,7 +482,7 @@ bool cRecordingInfo::Write(FILE *f, const char *Prefix) const if (channelID.Valid()) fprintf(f, "%sC %s%s%s\n", Prefix, *channelID.ToString(), channelName ? " " : "", channelName ? channelName : ""); event->Dump(f, Prefix, true); - fprintf(f, "%sF %.10g\n", Prefix, framesPerSecond); + fprintf(f, "%sF %s\n", Prefix, *dtoa(framesPerSecond, "%.10g")); fprintf(f, "%sP %d\n", Prefix, priority); fprintf(f, "%sL %d\n", Prefix, lifetime); if (aux) diff --git a/tools.c b/tools.c index efb9f164..8c03c868 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 2.27 2012/12/03 09:31:32 kls Exp $ + * $Id: tools.c 2.28 2012/12/06 09:40:02 kls Exp $ */ #include "tools.h" @@ -18,6 +18,7 @@ extern "C" { #include #undef boolean } +#include #include #include #include @@ -302,6 +303,31 @@ cString AddDirectory(const char *DirName, const char *FileName) return cString::sprintf("%s/%s", DirName && *DirName ? DirName : ".", FileName); } +double atod(const char *s) +{ + static lconv *loc = localeconv(); + char buf[strlen(s) + 1]; + char *p = buf; + while (*s) { + if (*s == '.') + *p = *loc->decimal_point; + else + *p = *s; + p++; + s++; + } + *p = 0; + return atof(buf); +} + +cString dtoa(double d, const char *Format) +{ + static lconv *loc = localeconv(); + char buf[16]; + snprintf(buf, sizeof(buf), Format, d); + return strreplace(buf, *loc->decimal_point, '.'); +} + cString itoa(int n) { char buf[16]; diff --git a/tools.h b/tools.h index 3e546a17..70c643fc 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 2.22 2012/09/30 11:02:21 kls Exp $ + * $Id: tools.h 2.23 2012/12/06 08:59:39 kls Exp $ */ #ifndef __TOOLS_H @@ -216,6 +216,14 @@ int64_t StrToNum(const char *s); bool StrInArray(const char *a[], const char *s); ///< Returns true if the string s is equal to one of the strings pointed ///< to by the (NULL terminated) array a. +double atod(const char *s); + ///< Converts the given string, which is a floating point number using a '.' as + ///< the decimal point, to a double value, independent of the currently selected + ///< locale. +cString dtoa(double d, const char *Format = "%f"); + ///< Converts the given double value to a string, making sure it uses a '.' as + ///< the decimal point, independent of the currently selected locale. + ///< If Format is given, it will be used instead of the default. cString itoa(int n); cString AddDirectory(const char *DirName, const char *FileName); bool EntriesOnSameFileSystem(const char *File1, const char *File2); diff --git a/vdr.c b/vdr.c index 821bc32f..88b8956f 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 2.44 2012/12/04 12:55:02 kls Exp $ + * $Id: vdr.c 2.45 2012/12/06 10:29:23 kls Exp $ */ #include @@ -174,7 +174,6 @@ int main(int argc, char *argv[]) // Initiate locale: setlocale(LC_ALL, ""); - setlocale(LC_NUMERIC, "C"); // makes sure any floating point numbers written use a decimal point // Command line options: -- cgit v1.2.3