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