mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-13 15:29:45 +03:00
libcamera: yaml_parser: Use C locale
When parsing configuration files on systems with differing locales, the use of strtod can produce different results, or in the worst case - fail to parse expected values. Fix this by using strtod_l() instead. To avoid constructing and destructing a locale_t instance for every use of strtod_l(), create an RAII class that wraps the locale_t and use it to provide a global "C" locale. Bug: https://bugs.libcamera.org/show_bug.cgi?id=174 Bug: https://github.com/raspberrypi/libcamera/issues/29 Reported-by: https://github.com/kralo Reported-by: Hannes Winkler <hanneswinkler2000@web.de> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
0081e4e6b2
commit
e8ae254970
1 changed files with 33 additions and 1 deletions
|
@ -31,6 +31,38 @@ namespace {
|
||||||
/* Empty static YamlObject as a safe result for invalid operations */
|
/* Empty static YamlObject as a safe result for invalid operations */
|
||||||
static const YamlObject empty;
|
static const YamlObject empty;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct a global RAII locale for use by all YAML parser instances to
|
||||||
|
* ensure consistency when parsing configuration files and types regardless of
|
||||||
|
* the system locale configuration.
|
||||||
|
*
|
||||||
|
* For more information see:
|
||||||
|
* - https://bugs.libcamera.org/show_bug.cgi?id=174
|
||||||
|
*/
|
||||||
|
class Locale
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Locale(const char *locale)
|
||||||
|
{
|
||||||
|
locale_ = newlocale(LC_ALL_MASK, locale, static_cast<locale_t>(0));
|
||||||
|
if (locale_ == static_cast<locale_t>(0))
|
||||||
|
LOG(YamlParser, Fatal)
|
||||||
|
<< "Failed to construct a locale";
|
||||||
|
}
|
||||||
|
|
||||||
|
~Locale()
|
||||||
|
{
|
||||||
|
freelocale(locale_);
|
||||||
|
}
|
||||||
|
|
||||||
|
locale_t locale() { return locale_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
locale_t locale_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Locale yamlLocale("C");
|
||||||
|
|
||||||
} /* namespace */
|
} /* namespace */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -283,7 +315,7 @@ std::optional<double> YamlObject::get() const
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
double value = std::strtod(value_.c_str(), &end);
|
double value = strtod_l(value_.c_str(), &end, yamlLocale.locale());
|
||||||
|
|
||||||
if ('\0' != *end || errno == ERANGE)
|
if ('\0' != *end || errno == ERANGE)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue