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 */
40class GrAutoLocaleSetter : public SkNoncopyable {
41public:
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
84private:
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