1 | /* |
2 | * Copyright 2015 Google Inc. |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | #ifndef GrAutoLocaleSetter_DEFINED |
9 | #define GrAutoLocaleSetter_DEFINED |
10 | |
11 | #include "include/gpu/GrTypes.h" |
12 | #include "include/private/SkNoncopyable.h" |
13 | |
14 | #if defined(SK_BUILD_FOR_WIN) |
15 | #include "include/core/SkString.h" |
16 | #endif |
17 | |
18 | #if !defined(SK_BUILD_FOR_ANDROID) |
19 | #include <locale.h> |
20 | #endif |
21 | |
22 | #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
23 | #include <xlocale.h> |
24 | #include <cstring> |
25 | #define HAVE_XLOCALE 1 |
26 | #else |
27 | #define HAVE_XLOCALE 0 |
28 | #endif |
29 | |
30 | #if defined(SK_BUILD_FOR_ANDROID) || defined(__UCLIBC__) || defined(_NEWLIB_VERSION) |
31 | #define HAVE_LOCALE_T 0 |
32 | #else |
33 | #define HAVE_LOCALE_T 1 |
34 | #endif |
35 | |
36 | /** |
37 | * Helper class for ensuring that we don't use the wrong locale when building shaders. Android |
38 | * doesn't support locale in the NDK, so this is a no-op there. |
39 | */ |
40 | class GrAutoLocaleSetter : public SkNoncopyable { |
41 | public: |
42 | GrAutoLocaleSetter (const char* name) { |
43 | #if defined(SK_BUILD_FOR_WIN) |
44 | fOldPerThreadLocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); |
45 | char* oldLocale = setlocale(LC_ALL, name); |
46 | if (oldLocale) { |
47 | fOldLocale = oldLocale; |
48 | fShouldRestoreLocale = true; |
49 | } else { |
50 | fShouldRestoreLocale = false; |
51 | } |
52 | #elif HAVE_LOCALE_T |
53 | #if HAVE_XLOCALE |
54 | // In xlocale nullptr means the C locale. |
55 | if (0 == strcmp(name, "C" )) { |
56 | name = nullptr; |
57 | } |
58 | #endif |
59 | fLocale = newlocale(LC_ALL_MASK, name, nullptr); |
60 | if (fLocale) { |
61 | fOldLocale = uselocale(fLocale); |
62 | } else { |
63 | fOldLocale = static_cast<locale_t>(nullptr); |
64 | } |
65 | #else |
66 | (void) name; // suppress unused param warning. |
67 | #endif |
68 | } |
69 | |
70 | ~GrAutoLocaleSetter () { |
71 | #if defined(SK_BUILD_FOR_WIN) |
72 | if (fShouldRestoreLocale) { |
73 | setlocale(LC_ALL, fOldLocale.c_str()); |
74 | } |
75 | _configthreadlocale(fOldPerThreadLocale); |
76 | #elif HAVE_LOCALE_T |
77 | if (fLocale) { |
78 | uselocale(fOldLocale); |
79 | freelocale(fLocale); |
80 | } |
81 | #endif |
82 | } |
83 | |
84 | private: |
85 | #if defined(SK_BUILD_FOR_WIN) |
86 | int fOldPerThreadLocale; |
87 | bool fShouldRestoreLocale; |
88 | SkString fOldLocale; |
89 | #elif HAVE_LOCALE_T |
90 | locale_t fOldLocale; |
91 | locale_t fLocale; |
92 | #endif |
93 | }; |
94 | |
95 | #undef HAVE_LOCALE_T |
96 | #undef HAVE_XLOCALE |
97 | |
98 | #endif |
99 | |