Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ScopedSafeLocale.hpp 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. #ifndef DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED
  17. #define DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED
  18. #include "../DistrhoUtils.hpp"
  19. #include <clocale>
  20. #if ! (defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
  21. # define DISTRHO_USE_NEWLOCALE
  22. #endif
  23. #if defined(DISTRHO_OS_WINDOWS) && __MINGW64_VERSION_MAJOR >= 5
  24. # define DISTRHO_USE_CONFIGTHREADLOCALE
  25. #endif
  26. START_NAMESPACE_DISTRHO
  27. // -----------------------------------------------------------------------
  28. // ScopedSafeLocale class definition
  29. /**
  30. ScopedSafeLocale is a handy class for setting current locale to C on constructor, and revert back on destructor.
  31. It tries to be thread-safe, but it is not always possible.
  32. Put it inside a scope of code where string conversions happen to ensure they are consistent across many systems.
  33. For example:
  34. ```
  35. // stack buffer to put converted float value in
  36. char strbuf[0xff];
  37. {
  38. // safe locale operations during this scope
  39. const ScopedSafeLocale sl;
  40. snprintf(strbuf, 0xff, "%f", value);
  41. }
  42. // do something with `strbuf` now, locale is reverted and left just as it was before
  43. ```
  44. */
  45. class ScopedSafeLocale {
  46. public:
  47. /*
  48. * Constructor.
  49. * Current system locale will saved, while "C" is set as the next one to use.
  50. */
  51. inline ScopedSafeLocale() noexcept;
  52. /*
  53. * Destructor.
  54. * System locale will revert back to the one saved during constructor.
  55. */
  56. inline ~ScopedSafeLocale() noexcept;
  57. private:
  58. #ifdef DISTRHO_USE_NEWLOCALE
  59. locale_t newloc, oldloc;
  60. #else
  61. # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
  62. const int oldthreadloc;
  63. # endif
  64. char* const oldloc;
  65. #endif
  66. DISTRHO_DECLARE_NON_COPYABLE(ScopedSafeLocale)
  67. DISTRHO_PREVENT_HEAP_ALLOCATION
  68. };
  69. // -----------------------------------------------------------------------
  70. // ScopedSafeLocale class implementation
  71. #ifdef DISTRHO_USE_NEWLOCALE
  72. static constexpr const locale_t kNullLocale = (locale_t)nullptr;
  73. #endif
  74. inline ScopedSafeLocale::ScopedSafeLocale() noexcept
  75. #ifdef DISTRHO_USE_NEWLOCALE
  76. : newloc(::newlocale(LC_NUMERIC_MASK, "C", kNullLocale)),
  77. oldloc(newloc != kNullLocale ? ::uselocale(newloc) : kNullLocale) {}
  78. #else
  79. # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
  80. : oldthreadloc(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)),
  81. # else
  82. :
  83. # endif
  84. oldloc(strdup(::setlocale(LC_NUMERIC, nullptr)))
  85. {
  86. ::setlocale(LC_NUMERIC, "C");
  87. }
  88. #endif
  89. inline ScopedSafeLocale::~ScopedSafeLocale() noexcept
  90. {
  91. #ifdef DISTRHO_USE_NEWLOCALE
  92. if (oldloc != kNullLocale)
  93. ::uselocale(oldloc);
  94. if (newloc != kNullLocale)
  95. ::freelocale(newloc);
  96. #else // DISTRHO_USE_NEWLOCALE
  97. if (oldloc != nullptr)
  98. {
  99. ::setlocale(LC_NUMERIC, oldloc);
  100. std::free(oldloc);
  101. }
  102. # ifdef DISTRHO_USE_CONFIGTHREADLOCALE
  103. if (oldthreadloc != -1)
  104. _configthreadlocale(oldthreadloc);
  105. # endif
  106. #endif // DISTRHO_USE_NEWLOCALE
  107. }
  108. // -----------------------------------------------------------------------
  109. #undef DISTRHO_USE_CONFIGTHREADLOCALE
  110. #undef DISTRHO_USE_NEWLOCALE
  111. END_NAMESPACE_DISTRHO
  112. #endif // DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED