comparison DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedSafeLocale.hpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #ifndef DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED
18 #define DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED
19
20 #include "../DistrhoUtils.hpp"
21
22 #include <clocale>
23
24 #if ! (defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
25 # define DISTRHO_USE_NEWLOCALE
26 #endif
27
28 #if defined(DISTRHO_OS_WINDOWS) && __MINGW64_VERSION_MAJOR >= 5
29 # define DISTRHO_USE_CONFIGTHREADLOCALE
30 #endif
31
32 START_NAMESPACE_DISTRHO
33
34 // -----------------------------------------------------------------------
35 // ScopedSafeLocale class definition
36
37 /**
38 ScopedSafeLocale is a handy class for setting current locale to C on constructor, and revert back on destructor.
39 It tries to be thread-safe, but it is not always possible.
40
41 Put it inside a scope of code where string conversions happen to ensure they are consistent across many systems.
42 For example:
43
44 ```
45 // stack buffer to put converted float value in
46 char strbuf[0xff];
47
48 {
49 // safe locale operations during this scope
50 const ScopedSafeLocale sl;
51 snprintf(strbuf, 0xff, "%f", value);
52 }
53
54 // do something with `strbuf` now, locale is reverted and left just as it was before
55 ```
56 */
57 class ScopedSafeLocale {
58 public:
59 /*
60 * Constructor.
61 * Current system locale will saved, while "C" is set as the next one to use.
62 */
63 inline ScopedSafeLocale() noexcept;
64
65 /*
66 * Destructor.
67 * System locale will revert back to the one saved during constructor.
68 */
69 inline ~ScopedSafeLocale() noexcept;
70
71 private:
72 #ifdef DISTRHO_USE_NEWLOCALE
73 locale_t newloc, oldloc;
74 #else
75 # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
76 const int oldthreadloc;
77 # endif
78 char* const oldloc;
79 #endif
80
81 DISTRHO_DECLARE_NON_COPYABLE(ScopedSafeLocale)
82 DISTRHO_PREVENT_HEAP_ALLOCATION
83 };
84
85 // -----------------------------------------------------------------------
86 // ScopedSafeLocale class implementation
87
88 #ifdef DISTRHO_USE_NEWLOCALE
89 static constexpr const locale_t kNullLocale = (locale_t)nullptr;
90 #endif
91
92 inline ScopedSafeLocale::ScopedSafeLocale() noexcept
93 #ifdef DISTRHO_USE_NEWLOCALE
94 : newloc(::newlocale(LC_NUMERIC_MASK, "C", kNullLocale)),
95 oldloc(newloc != kNullLocale ? ::uselocale(newloc) : kNullLocale) {}
96 #else
97 # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
98 : oldthreadloc(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)),
99 # else
100 :
101 # endif
102 oldloc(strdup(::setlocale(LC_NUMERIC, nullptr)))
103 {
104 ::setlocale(LC_NUMERIC, "C");
105 }
106 #endif
107
108 inline ScopedSafeLocale::~ScopedSafeLocale() noexcept
109 {
110 #ifdef DISTRHO_USE_NEWLOCALE
111 if (oldloc != kNullLocale)
112 ::uselocale(oldloc);
113 if (newloc != kNullLocale)
114 ::freelocale(newloc);
115 #else // DISTRHO_USE_NEWLOCALE
116 if (oldloc != nullptr)
117 {
118 ::setlocale(LC_NUMERIC, oldloc);
119 std::free(oldloc);
120 }
121
122 # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
123 if (oldthreadloc != -1)
124 _configthreadlocale(oldthreadloc);
125 # endif
126 #endif // DISTRHO_USE_NEWLOCALE
127 }
128
129 // -----------------------------------------------------------------------
130
131 #undef DISTRHO_USE_CONFIGTHREADLOCALE
132 #undef DISTRHO_USE_NEWLOCALE
133
134 END_NAMESPACE_DISTRHO
135
136 #endif // DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED