summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-05-05 20:02:23 +0200
committerRobin Gareus <robin@gareus.org>2016-05-05 20:02:48 +0200
commitf2c5522f0f0ddc70ebf182186b3cc821252dd24f (patch)
tree0b87b290eb07d18f221b2045a6942a398c0115ed /libs
parenta644212506dcf41ad0b90a3c38ccb2279b6054c5 (diff)
rework locale-guard for C and C++ locales
let's hope querying the C-locale is more lightweight than setting it on windows.
Diffstat (limited to 'libs')
-rw-r--r--libs/pbd/locale_guard.cc60
-rw-r--r--libs/pbd/pbd/locale_guard.h23
2 files changed, 55 insertions, 28 deletions
diff --git a/libs/pbd/locale_guard.cc b/libs/pbd/locale_guard.cc
index 4ec64984b0..c0d351febf 100644
--- a/libs/pbd/locale_guard.cc
+++ b/libs/pbd/locale_guard.cc
@@ -19,36 +19,62 @@
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <locale.h>
#include "pbd/locale_guard.h"
using namespace PBD;
-// try to avoid calling setlocale() recursively. this is not thread-safe.
-std::string PBD::LocaleGuard::current;
+/* The initial C++ locate is "C" regardless of the user's preferred locale.
+ * and affects std::sprintf() et al from <cstdio>
+ *
+ * the C locale from stlocale() matches the user's preferred locale
+ * and effects ::sprintf() et al from <stdio.h>
+ *
+ * Setting the C++ locale will change the C locale, but not the other way 'round.
+ * and some plugin may change either behind our back.
+ */
-LocaleGuard::LocaleGuard (const char* str)
- : old(0)
+LocaleGuard::LocaleGuard (const char*)
+ : old_c (0)
{
- if (current != str) {
- old = strdup (setlocale (LC_NUMERIC, NULL));
- if (strcmp (old, str)) {
- if (setlocale (LC_NUMERIC, str)) {
- current = str;
- }
- }
+ init ();
+}
+
+LocaleGuard::LocaleGuard ()
+ : old_c (0)
+{
+ init ();
+}
+
+void
+LocaleGuard::init ()
+{
+ char* actual = setlocale (LC_NUMERIC, NULL);
+ if (strcmp ("C", actual)) {
+ old_c = strdup (actual);
+ /* this changes both C++ and C locale */
+ std::locale::global (std::locale (std::locale::classic(), "C", std::locale::numeric));
}
+ assert (old_cpp == std::locale::classic ());
}
LocaleGuard::~LocaleGuard ()
{
- if (old) {
- if (setlocale (LC_NUMERIC, old)) {
- current = old;
- }
+ char* actual = setlocale (LC_NUMERIC, NULL);
+ std::locale current;
- free (old);
+ if (current != old_cpp) {
+ /* the C++ locale should always be "C", that's the default
+ * at application start, and ardour never changes it
+ * if it's not: some plugin meddled with it.
+ */
+ assert (old_cpp == std::locale::classic ());
+ std::locale::global (old_cpp);
}
+ if (old_c && strcmp (old_c, actual)) {
+ setlocale (LC_NUMERIC, old_c);
+ }
+ free (old_c);
}
-
diff --git a/libs/pbd/pbd/locale_guard.h b/libs/pbd/pbd/locale_guard.h
index dc82ab4483..3d37562ced 100644
--- a/libs/pbd/pbd/locale_guard.h
+++ b/libs/pbd/pbd/locale_guard.h
@@ -22,20 +22,21 @@
#include "pbd/libpbd_visibility.h"
-#include <string>
+#include <locale>
namespace PBD {
-struct LIBPBD_API LocaleGuard {
- LocaleGuard (const char*);
- ~LocaleGuard ();
-
- static std::string current;
-
-private:
- char* old;
-};
-
+ struct LIBPBD_API LocaleGuard {
+ public:
+ LocaleGuard ();
+ LocaleGuard (const char*); // deprecated
+ ~LocaleGuard ();
+
+ private:
+ void init ();
+ std::locale old_cpp;
+ char* old_c;
+ };
}
#endif /* __pbd_locale_guard__ */