2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-2001
5 Copyright (C) Simo Sorce 2001
6 Copyright (C) Andrew Bartlett 2011
7 Copyright (C) Jeremy Allison 1992-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/locale.h"
31 Case insensitive string compararison
33 _PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
35 codepoint_t c1=0, c2=0;
37 struct smb_iconv_handle *iconv_handle = get_iconv_handle();
39 /* handle null ptr comparisons to simplify the use in qsort */
40 if (s1 == s2) return 0;
41 if (s1 == NULL) return -1;
42 if (s2 == NULL) return 1;
45 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
46 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
55 if (c1 == INVALID_CODEPOINT ||
56 c2 == INVALID_CODEPOINT) {
57 /* what else can we do?? */
58 return strcasecmp(s1, s2);
61 if (toupper_m(c1) != toupper_m(c2)) {
70 Case insensitive string compararison, length limited
72 _PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
74 codepoint_t c1=0, c2=0;
76 struct smb_iconv_handle *iconv_handle = get_iconv_handle();
78 /* handle null ptr comparisons to simplify the use in qsort */
79 if (s1 == s2) return 0;
80 if (s1 == NULL) return -1;
81 if (s2 == NULL) return 1;
83 while (*s1 && *s2 && n) {
86 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
87 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
96 if (c1 == INVALID_CODEPOINT ||
97 c2 == INVALID_CODEPOINT) {
98 /* what else can we do?? */
99 return strcasecmp(s1, s2);
102 if (toupper_m(c1) != toupper_m(c2)) {
117 * @note The comparison is case-insensitive.
119 _PUBLIC_ bool strequal_m(const char *s1, const char *s2)
121 return strcasecmp_m(s1,s2) == 0;
125 Compare 2 strings (case sensitive).
127 _PUBLIC_ bool strcsequal(const char *s1,const char *s2)
134 return strcmp(s1,s2) == 0;
138 * Calculate the number of units (8 or 16-bit, depending on the
139 * destination charset), that would be needed to convert the input
140 * string which is expected to be in in src_charset encoding to the
141 * destination charset (which should be a unicode charset).
143 _PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic,
144 const char *s, charset_t src_charset, charset_t dst_charset)
152 while (*s && !(((uint8_t)*s) & 0x80)) {
163 codepoint_t c = next_codepoint_handle_ext(ic, s, src_charset, &c_size);
166 switch (dst_charset) {
171 /* Unicode char fits into 16 bits. */
174 /* Double-width unicode char - 32 bits. */
180 * this only checks ranges, and does not
181 * check for invalid codepoints
185 } else if (c < 0x800) {
187 } else if (c < 0x10000) {
195 * non-unicode encoding:
196 * assume that each codepoint fits into
197 * one unit in the destination encoding.
207 * Calculate the number of units (8 or 16-bit, depending on the
208 * destination charset), that would be needed to convert the input
209 * string which is expected to be in in src_charset encoding to the
210 * destination charset (which should be a unicode charset).
212 _PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset)
214 struct smb_iconv_handle *ic = get_iconv_handle();
215 return strlen_m_ext_handle(ic, s, src_charset, dst_charset);
218 _PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset,
219 const charset_t dst_charset)
224 return strlen_m_ext(s, src_charset, dst_charset) + 1;
228 * Calculate the number of 16-bit units that would be needed to convert
229 * the input string which is expected to be in CH_UNIX encoding to UTF16.
231 * This will be the same as the number of bytes in a string for single
232 * byte strings, but will be different for multibyte.
234 _PUBLIC_ size_t strlen_m(const char *s)
236 return strlen_m_ext(s, CH_UNIX, CH_UTF16LE);
240 Work out the number of multibyte chars in a string, including the NULL
243 _PUBLIC_ size_t strlen_m_term(const char *s)
249 return strlen_m(s) + 1;
253 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
254 * if a string is there, include the terminator.
257 _PUBLIC_ size_t strlen_m_term_null(const char *s)
272 Strchr and strrchr_m are a bit complex on general multi-byte strings.
274 _PUBLIC_ char *strchr_m(const char *src, char c)
277 struct smb_iconv_handle *ic = get_iconv_handle();
281 /* characters below 0x3F are guaranteed to not appear in
282 non-initial position in multi-byte charsets */
283 if ((c & 0xC0) == 0) {
284 return strchr(src, c);
287 /* this is quite a common operation, so we want it to be
288 fast. We optimise for the ascii case, knowing that all our
289 supported multi-byte character sets are ascii-compatible
290 (ie. they match for the first 128 chars) */
292 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
300 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
301 /* With compose characters we must restart from the beginning. JRA. */
307 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
309 return discard_const_p(char, s);
318 * Multibyte-character version of strrchr
320 _PUBLIC_ char *strrchr_m(const char *s, char c)
322 struct smb_iconv_handle *ic = get_iconv_handle();
329 /* characters below 0x3F are guaranteed to not appear in
330 non-initial position in multi-byte charsets */
331 if ((c & 0xC0) == 0) {
332 return strrchr(s, c);
335 /* this is quite a common operation, so we want it to be
336 fast. We optimise for the ascii case, knowing that all our
337 supported multi-byte character sets are ascii-compatible
338 (ie. they match for the first 128 chars). Also, in Samba
339 we only search for ascii characters in 'c' and that
340 in all mb character sets with a compound character
341 containing c, if 'c' is not a match at position
342 p, then p[-1] > 0x7f. JRA. */
345 size_t len = strlen(s);
354 /* Could be a match. Part of a multibyte ? */
356 (((unsigned char)cp[-1]) & 0x80)) {
357 /* Yep - go slow :-( */
361 /* No - we have a match ! */
371 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
373 ret = discard_const_p(char, s);
382 return True if any (multi-byte) character is lower case
384 _PUBLIC_ bool strhaslower(const char *string)
386 struct smb_iconv_handle *ic = get_iconv_handle();
392 s = next_codepoint_handle(ic, string, &c_size);
398 return true; /* that means it has lower case chars */
406 return True if any (multi-byte) character is upper case
408 _PUBLIC_ bool strhasupper(const char *string)
410 struct smb_iconv_handle *ic = get_iconv_handle();
416 s = next_codepoint_handle(ic, string, &c_size);
422 return true; /* that means it has upper case chars */