1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #pragma once
30
31 /**
32 * @file ctype.h
33 * @brief ASCII character classification.
34 */
35
36 #include <sys/cdefs.h>
37 #include <xlocale.h>
38
39 /* All the functions in this file are trivial, being but a single
40 * instruction on most architectures. For that reason, we inline them by
41 * default. This macro is meant for internal use only, so that we can
42 * also provide actual symbols for any caller that needs them.
43 */
44 #if !defined(__BIONIC_CTYPE_INLINE)
45 #define __BIONIC_CTYPE_INLINE static __inline
46 #endif
47
48 /** Internal implementation detail. Do not use. */
49 #define _CTYPE_U 0x01
50 /** Internal implementation detail. Do not use. */
51 #define _CTYPE_L 0x02
52 /** Internal implementation detail. Do not use. */
53 #define _CTYPE_D 0x04
54 /** Internal implementation detail. Do not use. */
55 #define _CTYPE_S 0x08
56 /** Internal implementation detail. Do not use. */
57 #define _CTYPE_P 0x10
58 /** Internal implementation detail. Do not use. */
59 #define _CTYPE_C 0x20
60 /** Internal implementation detail. Do not use. */
61 #define _CTYPE_X 0x40
62 /** Internal implementation detail. Do not use. */
63 #define _CTYPE_B 0x80
64 /** Internal implementation detail. Do not use. */
65 #define _CTYPE_R (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_D|_CTYPE_B)
66 /** Internal implementation detail. Do not use. */
67 #define _CTYPE_A (_CTYPE_L|_CTYPE_U)
68 /** Internal implementation detail. Do not use. */
69 #define _CTYPE_N _CTYPE_D
70
71 __BEGIN_DECLS
72
73 /** Internal implementation detail. Do not use. */
74 extern const char* _ctype_;
75
76 /**
77 * Returns the corresponding lower-case character if `ch` is upper-case, or undefined otherwise.
78 *
79 * Prefer tolower() instead.
80 */
_tolower(int __ch)81 __BIONIC_CTYPE_INLINE int _tolower(int __ch) {
82 return __ch | 0x20;
83 }
84
85 /**
86 * Returns the corresponding upper-case character if `ch` is lower-case, or undefined otherwise.
87 *
88 * Prefer toupper() instead.
89 */
_toupper(int __ch)90 __BIONIC_CTYPE_INLINE int _toupper(int __ch) {
91 // Using EOR rather than AND makes no difference on arm, but saves an
92 // instruction on arm64.
93 return __ch ^ 0x20;
94 }
95
96 /** Internal implementation detail. Do not use. */
97 __attribute__((__no_sanitize__("unsigned-integer-overflow")))
__bionic_ctype_in_range(unsigned __lo,int __ch,unsigned __hi)98 __BIONIC_CTYPE_INLINE int __bionic_ctype_in_range(unsigned __lo, int __ch, unsigned __hi) {
99 return (__BIONIC_CAST(static_cast, unsigned, __ch) - __lo) < (__hi - __lo + 1);
100 }
101
102 /** Returns true if `ch` is in `[A-Za-z]`. */
isalpha(int __ch)103 __BIONIC_CTYPE_INLINE int isalpha(int __ch) {
104 return __bionic_ctype_in_range('a', _tolower(__ch), 'z');
105 }
106
107 /** Returns true if `ch` is a space or tab. */
isblank(int __ch)108 __BIONIC_CTYPE_INLINE int isblank(int __ch) {
109 return __ch == ' ' || __ch == '\t';
110 }
111
112 /** Returns true if `ch` is a control character (any character before space, plus DEL). */
iscntrl(int __ch)113 __BIONIC_CTYPE_INLINE int iscntrl(int __ch) {
114 return (__BIONIC_CAST(static_cast, unsigned, __ch) < ' ') || __ch == 0x7f;
115 }
116
117 /** Returns true if `ch` is in `[0-9]`. */
isdigit(int __ch)118 __BIONIC_CTYPE_INLINE int isdigit(int __ch) {
119 return __bionic_ctype_in_range('0', __ch, '9');
120 }
121
122 /** Returns true if `ch` is `[A-Za-z0-9]` or punctuation. */
isgraph(int __ch)123 __BIONIC_CTYPE_INLINE int isgraph(int __ch) {
124 return __bionic_ctype_in_range('!', __ch, '~');
125 }
126
127 /** Returns true if `ch` is in `[a-z]`. */
islower(int __ch)128 __BIONIC_CTYPE_INLINE int islower(int __ch) {
129 return __bionic_ctype_in_range('a', __ch, 'z');
130 }
131
132 /** Returns true if `ch` is `[A-Za-z0-9]` or punctuation or space. */
isprint(int __ch)133 __BIONIC_CTYPE_INLINE int isprint(int __ch) {
134 return __bionic_ctype_in_range(' ', __ch, '~');
135 }
136
137 /** Returns true if `ch` is in `[ \f\n\r\t\v]`. */
isspace(int __ch)138 __BIONIC_CTYPE_INLINE int isspace(int __ch) {
139 return __ch == ' ' || __bionic_ctype_in_range('\t', __ch, '\r');
140 }
141
142 /** Returns true if `ch` is in `[A-Z]`. */
isupper(int __ch)143 __BIONIC_CTYPE_INLINE int isupper(int __ch) {
144 return __bionic_ctype_in_range('A', __ch, 'Z');
145 }
146
147 /** Returns true if `ch` is in `[0-9A-Fa-f]`. */
isxdigit(int __ch)148 __BIONIC_CTYPE_INLINE int isxdigit(int __ch) {
149 return isdigit(__ch) || __bionic_ctype_in_range('a', _tolower(__ch), 'f') ;
150 }
151
152 /** Returns true if `ch` is in `[A-Za-z0-9]`. */
isalnum(int __ch)153 __BIONIC_CTYPE_INLINE int isalnum(int __ch) {
154 return isalpha(__ch) || isdigit(__ch);
155 }
156
157 /** Returns true if `ch` is punctuation. */
ispunct(int __ch)158 __BIONIC_CTYPE_INLINE int ispunct(int __ch) {
159 return isgraph(__ch) && !isalnum(__ch);
160 }
161
162 /** Returns the corresponding lower-case character if `ch` is upper-case, or `ch` otherwise. */
tolower(int __ch)163 __BIONIC_CTYPE_INLINE int tolower(int __ch) {
164 return (__bionic_ctype_in_range('A', __ch, 'Z')) ? _tolower(__ch) : __ch;
165 }
166
167 /** Returns the corresponding upper-case character if `ch` is lower-case, or `ch` otherwise. */
toupper(int __ch)168 __BIONIC_CTYPE_INLINE int toupper(int __ch) {
169 return (__bionic_ctype_in_range('a', __ch, 'z')) ? _toupper(__ch) : __ch;
170 }
171
172 /** Returns true if `ch` is less than 0x80. */
isascii(int __ch)173 __BIONIC_CTYPE_INLINE int isascii(int __ch) {
174 return __BIONIC_CAST(static_cast, unsigned, __ch) < 0x80;
175 }
176
177 /** Returns `ch & 0x7f`. */
toascii(int __ch)178 __BIONIC_CTYPE_INLINE int toascii(int __ch) {
179 return __ch & 0x7f;
180 }
181
182 /** Like isalnum() but with an ignored `locale_t`. */
isalnum_l(int __ch,locale_t __l)183 __BIONIC_CTYPE_INLINE int isalnum_l(int __ch, locale_t __l) {
184 return isalnum(__ch);
185 }
186
187 /** Like isalpha() but with an ignored `locale_t`. */
isalpha_l(int __ch,locale_t __l)188 __BIONIC_CTYPE_INLINE int isalpha_l(int __ch, locale_t __l) {
189 return isalpha(__ch);
190 }
191
192 /** Like isblank() but with an ignored `locale_t`. */
isblank_l(int __ch,locale_t __l)193 __BIONIC_CTYPE_INLINE int isblank_l(int __ch, locale_t __l) {
194 return isblank(__ch);
195 }
196
197 /** Like iscntrl() but with an ignored `locale_t`. */
iscntrl_l(int __ch,locale_t __l)198 __BIONIC_CTYPE_INLINE int iscntrl_l(int __ch, locale_t __l) {
199 return iscntrl(__ch);
200 }
201
202 /** Like isdigit() but with an ignored `locale_t`. */
isdigit_l(int __ch,locale_t __l)203 __BIONIC_CTYPE_INLINE int isdigit_l(int __ch, locale_t __l) {
204 return isdigit(__ch);
205 }
206
207 /** Like isgraph() but with an ignored `locale_t`. */
isgraph_l(int __ch,locale_t __l)208 __BIONIC_CTYPE_INLINE int isgraph_l(int __ch, locale_t __l) {
209 return isgraph(__ch);
210 }
211
212 /** Like islower() but with an ignored `locale_t`. */
islower_l(int __ch,locale_t __l)213 __BIONIC_CTYPE_INLINE int islower_l(int __ch, locale_t __l) {
214 return islower(__ch);
215 }
216
217 /** Like isprint() but with an ignored `locale_t`. */
isprint_l(int __ch,locale_t __l)218 __BIONIC_CTYPE_INLINE int isprint_l(int __ch, locale_t __l) {
219 return isprint(__ch);
220 }
221
222 /** Like ispunct() but with an ignored `locale_t`. */
ispunct_l(int __ch,locale_t __l)223 __BIONIC_CTYPE_INLINE int ispunct_l(int __ch, locale_t __l) {
224 return ispunct(__ch);
225 }
226
227 /** Like isspace() but with an ignored `locale_t`. */
isspace_l(int __ch,locale_t __l)228 __BIONIC_CTYPE_INLINE int isspace_l(int __ch, locale_t __l) {
229 return isspace(__ch);
230 }
231
232 /** Like isupper() but with an ignored `locale_t`. */
isupper_l(int __ch,locale_t __l)233 __BIONIC_CTYPE_INLINE int isupper_l(int __ch, locale_t __l) {
234 return isupper(__ch);
235 }
236
237 /** Like isxdigit() but with an ignored `locale_t`. */
isxdigit_l(int __ch,locale_t __l)238 __BIONIC_CTYPE_INLINE int isxdigit_l(int __ch, locale_t __l) {
239 return isxdigit(__ch);
240 }
241
242 /** Like tolower() but with an ignored `locale_t`. */
tolower_l(int __ch,locale_t __l)243 __BIONIC_CTYPE_INLINE int tolower_l(int __ch, locale_t __l) {
244 return tolower(__ch);
245 }
246
247 /** Like toupper() but with an ignored `locale_t`. */
toupper_l(int __ch,locale_t __l)248 __BIONIC_CTYPE_INLINE int toupper_l(int __ch, locale_t __l) {
249 return toupper(__ch);
250 }
251
252 __END_DECLS
253