relibc/header/ctype/mod.rs
1//! `ctype.h` implementation.
2//!
3//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/ctype.h.html>.
4
5use crate::{header::bits_locale_t::locale_t, platform::types::c_int};
6
7/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isalnum.html>.
8///
9/// Tests whether `c` is a character of class alpha or digit in the current
10/// locale.
11///
12/// Returns a non-zero value if true, 0 if false.
13///
14/// The list of character classes defined by POSIX is specified here:
15/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
16#[unsafe(no_mangle)]
17pub extern "C" fn isalnum(c: c_int) -> c_int {
18 c_int::from(isdigit(c) != 0 || isalpha(c) != 0)
19}
20
21// TODO make use of `loc`.
22/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isalnum_l.html>.
23///
24/// Tests whether `c` is a character of class alpha or digit in the locale
25/// specified by `loc`.
26///
27/// Returns a non-zero value if true, 0 if false.
28///
29/// The list of character classes defined by POSIX is specified here:
30/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
31#[unsafe(no_mangle)]
32pub extern "C" fn isalnum_l(c: c_int, _loc: locale_t) -> c_int {
33 isalnum(c)
34}
35
36/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isalpha.html>.
37///
38/// Tests whether `c` is a character of class alpha in the current locale.
39///
40/// Returns a non-zero value if true, 0 if false.
41///
42/// The list of character classes defined by POSIX is specified here:
43/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
44#[unsafe(no_mangle)]
45pub extern "C" fn isalpha(c: c_int) -> c_int {
46 c_int::from(islower(c) != 0 || isupper(c) != 0)
47}
48
49// TODO make use of `loc`.
50/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isalpha_l.html>.
51///
52/// Tests whether `c` is a character of class alpha in the locale specified
53/// by `loc`.
54///
55/// Returns a non-zero value if true, 0 if false.
56///
57/// The list of character classes defined by POSIX is specified here:
58/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
59#[unsafe(no_mangle)]
60pub extern "C" fn isalpha_l(c: c_int, _loc: locale_t) -> c_int {
61 isalpha(c)
62}
63
64/// See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html>.
65///
66/// Tests whether `c` is a 7bit US-ASCII character code.
67///
68/// Returns a non-zero value if true, 0 if false.
69///
70/// # Deprecated
71/// The `isascii()` function was marked obsolescent in the Open Group Base
72/// Specifications Issue 7, and removed in Issue 8.
73///
74/// Not considered portable for localized applications.
75#[deprecated]
76#[unsafe(no_mangle)]
77pub extern "C" fn isascii(c: c_int) -> c_int {
78 c_int::from((c & !0x7f) == 0)
79}
80
81/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isblank.html>.
82///
83/// Tests whether `c` is a character of class blank in the current locale.
84///
85/// Returns a non-zero value if true, 0 if false.
86///
87/// The list of character classes defined by POSIX is specified here:
88/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
89#[unsafe(no_mangle)]
90pub extern "C" fn isblank(c: c_int) -> c_int {
91 c_int::from(c == c_int::from(b' ') || c == c_int::from(b'\t'))
92}
93
94// TODO make use of `loc`.
95/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isblank_l.html>.
96///
97/// Tests whether `c` is a character of class blank in the locale specified
98/// by `loc`.
99///
100/// Returns a non-zero value if true, 0 if false.
101///
102/// The list of character classes defined by POSIX is specified here:
103/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
104#[unsafe(no_mangle)]
105pub extern "C" fn isblank_l(c: c_int, _loc: locale_t) -> c_int {
106 isblank(c)
107}
108
109/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/iscntrl.html>.
110///
111/// Tests whether `c` is a character of class cntrl in the current locale.
112///
113/// Returns a non-zero value if true, 0 if false.
114///
115/// The list of character classes defined by POSIX is specified here:
116/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
117#[unsafe(no_mangle)]
118pub extern "C" fn iscntrl(c: c_int) -> c_int {
119 c_int::from((0x00..=0x1f).contains(&c) || c == 0x7f)
120}
121
122// TODO make use of `loc`.
123/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/iscntrl_l.html>.
124///
125/// Tests whether `c` is a character of class cntrl in the locale specified
126/// by `loc`.
127///
128/// Returns a non-zero value if true, 0 if false.
129///
130/// The list of character classes defined by POSIX is specified here:
131/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
132#[unsafe(no_mangle)]
133pub extern "C" fn iscntrl_l(c: c_int, _loc: locale_t) -> c_int {
134 iscntrl(c)
135}
136
137/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isdigit.html>.
138///
139/// Tests whether `c` is a character of class digit in the current locale.
140///
141/// Returns a non-zero value if true, 0 if false.
142///
143/// The list of character classes defined by POSIX is specified here:
144/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
145#[unsafe(no_mangle)]
146pub extern "C" fn isdigit(c: c_int) -> c_int {
147 c_int::from(c >= c_int::from(b'0') && c <= c_int::from(b'9'))
148}
149
150// TODO make use of `loc`.
151/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isdigit_l.html>.
152///
153/// Tests whether `c` is a character of class digit in the locale specified
154/// by `loc`.
155///
156/// Returns a non-zero value if true, 0 if false.
157///
158/// The list of character classes defined by POSIX is specified here:
159/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
160#[unsafe(no_mangle)]
161pub extern "C" fn isdigit_l(c: c_int, _loc: locale_t) -> c_int {
162 isdigit(c)
163}
164
165/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isgraph.html>.
166///
167/// Tests whether `c` is a character of class graph (a character with a
168/// visible representation) in the current locale.
169///
170/// Returns a non-zero value if true, 0 if false.
171///
172/// The list of character classes defined by POSIX is specified here:
173/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
174#[unsafe(no_mangle)]
175pub extern "C" fn isgraph(c: c_int) -> c_int {
176 c_int::from((0x21..=0x7e).contains(&c))
177}
178
179// TODO make use of `loc`.
180/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isgraph_l.html>.
181///
182/// Tests whether `c` is a character of class graph (a character with a
183/// visible representation) in the locale specified by `loc`.
184///
185/// Returns a non-zero value if true, 0 if false.
186///
187/// The list of character classes defined by POSIX is specified here:
188/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
189#[unsafe(no_mangle)]
190pub extern "C" fn isgraph_l(c: c_int, _loc: locale_t) -> c_int {
191 isgraph(c)
192}
193
194/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/islower.html>.
195///
196/// Tests whether `c` is a character of class lower (a lowercase letter) in the
197/// current locale.
198///
199/// Returns a non-zero value if true, 0 if false.
200///
201/// The list of character classes defined by POSIX is specified here:
202/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
203#[unsafe(no_mangle)]
204pub extern "C" fn islower(c: c_int) -> c_int {
205 c_int::from(c >= c_int::from(b'a') && c <= c_int::from(b'z'))
206}
207
208// TODO make use of `loc`.
209/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/islower_l.html>.
210///
211/// Tests whether `c` is a character of class lower (a lowercase letter) in the
212/// locale specified by `loc`.
213///
214/// Returns a non-zero value if true, 0 if false.
215///
216/// The list of character classes defined by POSIX is specified here:
217/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
218#[unsafe(no_mangle)]
219pub extern "C" fn islower_l(c: c_int, _loc: locale_t) -> c_int {
220 islower(c)
221}
222
223/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isprint.html>.
224///
225/// Tests whether `c` is a character of class print (a printable character) in
226/// the current locale.
227///
228/// Returns a non-zero value if true, 0 if false.
229///
230/// The list of character classes defined by POSIX is specified here:
231/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
232#[unsafe(no_mangle)]
233pub extern "C" fn isprint(c: c_int) -> c_int {
234 c_int::from((0x20..0x7f).contains(&c))
235}
236
237// TODO make use of `loc`.
238/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isprint_l.html>.
239///
240/// Tests whether `c` is a character of class print (a printable character) in
241/// the locale specified by `loc`.
242///
243/// Returns a non-zero value if true, 0 if false.
244///
245/// The list of character classes defined by POSIX is specified here:
246/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
247#[unsafe(no_mangle)]
248pub extern "C" fn isprint_l(c: c_int, _loc: locale_t) -> c_int {
249 isprint(c)
250}
251
252/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/ispunct.html>.
253///
254/// Tests whether `c` is a character of class punct (a punctuation character)
255/// in the current locale.
256///
257/// Returns a non-zero value if true, 0 if false.
258///
259/// The list of character classes defined by POSIX is specified here:
260/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
261#[unsafe(no_mangle)]
262pub extern "C" fn ispunct(c: c_int) -> c_int {
263 c_int::from(
264 (c >= c_int::from(b'!') && c <= c_int::from(b'/'))
265 || (c >= c_int::from(b':') && c <= c_int::from(b'@'))
266 || (c >= c_int::from(b'[') && c <= c_int::from(b'`'))
267 || (c >= c_int::from(b'{') && c <= c_int::from(b'~')),
268 )
269}
270
271// TODO make use of `loc`.
272/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/ispunct_l.html>.
273///
274/// Tests whether `c` is a character of class punct (a punctuation character)
275/// in the locale specified by `loc`.
276///
277/// Returns a non-zero value if true, 0 if false.
278///
279/// The list of character classes defined by POSIX is specified here:
280/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
281#[unsafe(no_mangle)]
282pub extern "C" fn ispunct_l(c: c_int, _loc: locale_t) -> c_int {
283 ispunct(c)
284}
285
286/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isspace.html>.
287///
288/// Tests whether `c` is a character of class space (a white-space character)
289/// in the current locale.
290///
291/// Returns a non-zero value if true, 0 if false.
292///
293/// The list of character classes defined by POSIX is specified here:
294/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
295#[unsafe(no_mangle)]
296pub extern "C" fn isspace(c: c_int) -> c_int {
297 c_int::from(
298 c == c_int::from(b' ')
299 || c == c_int::from(b'\t')
300 || c == c_int::from(b'\n')
301 || c == c_int::from(b'\r')
302 || c == 0x0b
303 || c == 0x0c,
304 )
305}
306
307// TODO make use of `loc`.
308/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isspace_l.html>.
309///
310/// Tests whether `c` is a character of class space (a white-space character)
311/// in the locale specified by `loc`.
312///
313/// Returns a non-zero value if true, 0 if false.
314///
315/// The list of character classes defined by POSIX is specified here:
316/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
317#[unsafe(no_mangle)]
318pub extern "C" fn isspace_l(c: c_int, _loc: locale_t) -> c_int {
319 isspace(c)
320}
321
322/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isupper.html>.
323///
324/// Tests whether `c` is a character of class upper (an uppercase letter) in
325/// the current locale.
326///
327/// Returns a non-zero value if true, 0 if false.
328///
329/// The list of character classes defined by POSIX is specified here:
330/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
331#[unsafe(no_mangle)]
332pub extern "C" fn isupper(c: c_int) -> c_int {
333 c_int::from(c >= c_int::from(b'A') && c <= c_int::from(b'Z'))
334}
335
336// TODO make use of `loc`.
337/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isupper_l.html>.
338///
339/// Tests whether `c` is a character of class upper (an uppercase letter) in
340/// the locale specified by `loc`.
341///
342/// Returns a non-zero value if true, 0 if false.
343///
344/// The list of character classes defined by POSIX is specified here:
345/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
346#[unsafe(no_mangle)]
347pub extern "C" fn isupper_l(c: c_int, _loc: locale_t) -> c_int {
348 isupper(c)
349}
350
351/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isxdigit.html>.
352///
353/// Tests whether `c` is a character of class xdigit (a hexadecimal digit) in
354/// the current locale.
355///
356/// Returns a non-zero value if true, 0 if false.
357///
358/// The list of character classes defined by POSIX is specified here:
359/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
360#[unsafe(no_mangle)]
361pub extern "C" fn isxdigit(c: c_int) -> c_int {
362 c_int::from(isdigit(c) != 0 || (c | 32 >= c_int::from(b'a') && c | 32 <= c_int::from(b'f')))
363}
364
365// TODO make use of `loc`.
366/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/isxdigit_l.html>.
367///
368/// Tests whether `c` is a character of class xdigit (a hexadecimal digit) in
369/// the locale specified by `loc`.
370///
371/// Returns a non-zero value if true, 0 if false.
372///
373/// The list of character classes defined by POSIX is specified here:
374/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
375#[unsafe(no_mangle)]
376pub extern "C" fn isxdigit_l(c: c_int, _loc: locale_t) -> c_int {
377 isxdigit(c)
378}
379
380/// See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/toascii.html>.
381///
382/// Converts `c` to a 7bit ASCII character.
383///
384/// # Deprecated
385/// The `toascii()` function was marked obsolescent in the Open Group Base
386/// Specifications Issue 7, and removed in Issue 8.
387///
388/// Not considered portable for localized applications.
389#[deprecated]
390#[unsafe(no_mangle)]
391pub extern "C" fn toascii(c: c_int) -> c_int {
392 c & 0x7f
393}
394
395/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/tolower.html>.
396///
397/// Returns the corresponding lowercase character for `c` according to the
398/// current locale, otherwise returns the input unchanged.
399///
400/// The list of character classes defined by POSIX is specified here:
401/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
402#[unsafe(no_mangle)]
403pub extern "C" fn tolower(c: c_int) -> c_int {
404 if isupper(c) != 0 { c | 0x20 } else { c }
405}
406
407// TODO make use of `loc`.
408/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/tolower_l.html>.
409///
410/// Returns the corresponding lowercase character for `c` according to the
411/// locale specified by `loc`, otherwise returns the input unchanged.
412///
413/// The list of character classes defined by POSIX is specified here:
414/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
415#[unsafe(no_mangle)]
416pub extern "C" fn tolower_l(c: c_int, _loc: locale_t) -> c_int {
417 tolower(c)
418}
419
420/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/toupper.html>.
421///
422/// Returns the corresponding uppercase character for `c` according to the
423/// current locale, otherwise returns the input unchanged.
424///
425/// The list of character classes defined by POSIX is specified here:
426/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
427#[unsafe(no_mangle)]
428pub extern "C" fn toupper(c: c_int) -> c_int {
429 if islower(c) != 0 { c & !0x20 } else { c }
430}
431
432// TODO make use of `loc`.
433/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/toupper_l.html>.
434///
435/// Returns the corresponding uppercase character for `c` according to the
436/// locale specified by `loc`, otherwise returns the input unchanged.
437///
438/// The list of character classes defined by POSIX is specified here:
439/// <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html>
440#[unsafe(no_mangle)]
441pub extern "C" fn toupper_l(c: c_int, _loc: locale_t) -> c_int {
442 toupper(c)
443}