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) || defined(__FreeBSD__)
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:
GrAutoLocaleSetter(const char * name)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 
~GrAutoLocaleSetter()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