1 /*
2  * Copyright 2011-2020 Max Kellermann <max.kellermann@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef CHAR_UTIL_HXX
31 #define CHAR_UTIL_HXX
32 
33 #ifdef _UNICODE
34 #include "WCharUtil.hxx"
35 #endif
36 
37 constexpr bool
IsASCII(const unsigned char ch)38 IsASCII(const unsigned char ch) noexcept
39 {
40 	return ch < 0x80;
41 }
42 
43 constexpr bool
IsASCII(const char ch)44 IsASCII(const char ch) noexcept
45 {
46 	return IsASCII((unsigned char)ch);
47 }
48 
49 constexpr bool
IsWhitespaceOrNull(const char ch)50 IsWhitespaceOrNull(const char ch) noexcept
51 {
52 	return (unsigned char)ch <= 0x20;
53 }
54 
55 constexpr bool
IsWhitespaceNotNull(const char ch)56 IsWhitespaceNotNull(const char ch) noexcept
57 {
58 	return ch > 0 && ch <= 0x20;
59 }
60 
61 /**
62  * Is the given character whitespace?  This calls the faster one of
63  * IsWhitespaceOrNull() or IsWhitespaceNotNull().  Use this if you
64  * want the fastest implementation, and you don't care if a null byte
65  * matches.
66  */
67 constexpr bool
IsWhitespaceFast(const char ch)68 IsWhitespaceFast(const char ch) noexcept
69 {
70 	return IsWhitespaceOrNull(ch);
71 }
72 
73 /**
74  * Is this a non-printable ASCII character?  Returns false for
75  * non-ASCII characters.
76  *
77  * Note that this is not the opposite of IsNonPrintableASCII().
78  */
79 constexpr bool
IsPrintableASCII(char ch)80 IsPrintableASCII(char ch) noexcept
81 {
82 	return (signed char)ch >= 0x20;
83 }
84 
85 /**
86  * Is this a non-printable character?  Returns false for non-ASCII characters.
87  *
88  * Note that this is not the opposite of IsPrintableASCII()
89  */
90 constexpr bool
IsNonPrintableASCII(char ch)91 IsNonPrintableASCII(char ch) noexcept
92 {
93 	return (unsigned char)ch < 0x20;
94 }
95 
96 constexpr bool
IsDigitASCII(char ch)97 IsDigitASCII(char ch) noexcept
98 {
99 	return ch >= '0' && ch <= '9';
100 }
101 
102 constexpr bool
IsUpperAlphaASCII(char ch)103 IsUpperAlphaASCII(char ch) noexcept
104 {
105 	return ch >= 'A' && ch <= 'Z';
106 }
107 
108 constexpr bool
IsLowerAlphaASCII(char ch)109 IsLowerAlphaASCII(char ch) noexcept
110 {
111 	return ch >= 'a' && ch <= 'z';
112 }
113 
114 constexpr bool
IsAlphaASCII(char ch)115 IsAlphaASCII(char ch) noexcept
116 {
117 	return IsUpperAlphaASCII(ch) || IsLowerAlphaASCII(ch);
118 }
119 
120 constexpr bool
IsAlphaNumericASCII(char ch)121 IsAlphaNumericASCII(char ch) noexcept
122 {
123 	return IsAlphaASCII(ch) || IsDigitASCII(ch);
124 }
125 
126 /**
127  * Convert the specified ASCII character (0x00..0x7f) to upper case.
128  * Unlike toupper(), it ignores the system locale.
129  */
130 constexpr char
ToUpperASCII(char ch)131 ToUpperASCII(char ch) noexcept
132 {
133 	return ch >= 'a' && ch <= 'z'
134 		? (ch - ('a' - 'A'))
135 		: ch;
136 }
137 
138 /**
139  * Convert the specified ASCII character (0x00..0x7f) to lower case.
140  * Unlike tolower(), it ignores the system locale.
141  */
142 constexpr char
ToLowerASCII(char ch)143 ToLowerASCII(char ch) noexcept
144 {
145 	return ch >= 'A' && ch <= 'Z'
146 		? (ch + ('a' - 'A'))
147 		: ch;
148 }
149 
150 constexpr bool
IsHexDigit(char ch)151 IsHexDigit(char ch) noexcept
152 {
153 	return IsDigitASCII(ch) ||
154 		(ch >= 'a' && ch <= 'f') ||
155 		(ch >= 'A' && ch <= 'F');
156 }
157 
158 #endif
159