summaryrefslogtreecommitdiffstats
path: root/gl/setlocale_null-unlocked.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/setlocale_null-unlocked.c')
-rw-r--r--gl/setlocale_null-unlocked.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/gl/setlocale_null-unlocked.c b/gl/setlocale_null-unlocked.c
new file mode 100644
index 00000000..0a86f0df
--- /dev/null
+++ b/gl/setlocale_null-unlocked.c
@@ -0,0 +1,149 @@
1/* Query the name of the current global locale, without locking.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
3
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
18
19#include <config.h>
20
21/* Specification. */
22#include "setlocale_null.h"
23
24#include <errno.h>
25#include <locale.h>
26#include <string.h>
27#if defined _WIN32 && !defined __CYGWIN__
28# include <wchar.h>
29#endif
30
31/* Use the system's setlocale() function, not the gnulib override, here. */
32#undef setlocale
33
34const char *
35setlocale_null_unlocked (int category)
36{
37 const char *result = setlocale (category, NULL);
38
39#ifdef __ANDROID__
40 if (result == NULL)
41 switch (category)
42 {
43 case LC_CTYPE:
44 case LC_NUMERIC:
45 case LC_TIME:
46 case LC_COLLATE:
47 case LC_MONETARY:
48 case LC_MESSAGES:
49 case LC_ALL:
50 case LC_PAPER:
51 case LC_NAME:
52 case LC_ADDRESS:
53 case LC_TELEPHONE:
54 case LC_MEASUREMENT:
55 result = "C";
56 break;
57 default:
58 break;
59 }
60#endif
61
62 return result;
63}
64
65int
66setlocale_null_r_unlocked (int category, char *buf, size_t bufsize)
67{
68#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
69 /* On native Windows, nowadays, the setlocale() implementation is based
70 on _wsetlocale() and uses malloc() for the result. We are better off
71 using _wsetlocale() directly. */
72 const wchar_t *result = _wsetlocale (category, NULL);
73
74 if (result == NULL)
75 {
76 /* CATEGORY is invalid. */
77 if (bufsize > 0)
78 /* Return an empty string in BUF.
79 This is a convenience for callers that don't want to write explicit
80 code for handling EINVAL. */
81 buf[0] = '\0';
82 return EINVAL;
83 }
84 else
85 {
86 size_t length = wcslen (result);
87 if (length < bufsize)
88 {
89 size_t i;
90
91 /* Convert wchar_t[] -> char[], assuming plain ASCII. */
92 for (i = 0; i <= length; i++)
93 buf[i] = result[i];
94
95 return 0;
96 }
97 else
98 {
99 if (bufsize > 0)
100 {
101 /* Return a truncated result in BUF.
102 This is a convenience for callers that don't want to write
103 explicit code for handling ERANGE. */
104 size_t i;
105
106 /* Convert wchar_t[] -> char[], assuming plain ASCII. */
107 for (i = 0; i < bufsize; i++)
108 buf[i] = result[i];
109 buf[bufsize - 1] = '\0';
110 }
111 return ERANGE;
112 }
113 }
114#else
115 const char *result = setlocale_null_unlocked (category);
116
117 if (result == NULL)
118 {
119 /* CATEGORY is invalid. */
120 if (bufsize > 0)
121 /* Return an empty string in BUF.
122 This is a convenience for callers that don't want to write explicit
123 code for handling EINVAL. */
124 buf[0] = '\0';
125 return EINVAL;
126 }
127 else
128 {
129 size_t length = strlen (result);
130 if (length < bufsize)
131 {
132 memcpy (buf, result, length + 1);
133 return 0;
134 }
135 else
136 {
137 if (bufsize > 0)
138 {
139 /* Return a truncated result in BUF.
140 This is a convenience for callers that don't want to write
141 explicit code for handling ERANGE. */
142 memcpy (buf, result, bufsize - 1);
143 buf[bufsize - 1] = '\0';
144 }
145 return ERANGE;
146 }
147 }
148#endif
149}