2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: DtNlUtils.c /main/10 1999/10/15 12:07:23 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /*****************************************************************************/
32 /* This file contains the Dt versions of common string functions, which */
33 /* have not yet been provided by the HP-UX platform. */
34 /* These functions know how to handle multi-byte strings. */
36 /*****************************************************************************/
39 #include <Dt/DtNlUtils.h>
40 #include "DtSvcLock.h"
45 Boolean _DtNl_is_multibyte = False;
50 * Dt nls initialization function.
51 * will see if multibyte characters are
52 * supported for the locale. If multibyte characters are not supported,
53 * then all of our string utilites simply call the standard libc function.
60 static Boolean first = True;
64 _DtSvcProcessUnlock();
69 _DtSvcProcessUnlock();
72 _DtNl_is_multibyte = True;
74 _DtNl_is_multibyte = False;
78 * Dt version of strtok(s1, s2).
79 * Returns a pointer to the span of characters in s1 terminated by
80 * one of the characters in s2. Only s1 can be multibyte.
93 /* Use standard libc function, if no multibyte */
94 if (!_DtNl_is_multibyte)
95 return(strtok(s1, s2));
98 * If this is the first call, save the string pointer, and bypass
99 * any leading separators.
102 ptr = s1 + Dt_strspn(s1, s2);
104 /* A Null string pointer has no tokens */
108 /* Find out where the first terminator is */
109 if ((len = Dt_strcspn(ptr, s2)) <= 0)
115 /* Keep track of where the token started */
118 /* Null out the terminator; we need to know how many bytes are
119 * occupied by the terminator, so that we can skip over it to
120 * the next character.
123 * We have to take care of the case when mblen() returns -1.
125 offset = mblen(ptr + len, MB_CUR_MAX);
129 ptr += (len + offset);
132 * In preparation for the next pass, skip any other occurrances of
133 * the terminator characters which were joined with the terminator
134 * we first encountered.
136 len = Dt_strspn(ptr, s2);
153 /* Use standard libc function, if no multibyte */
154 if (!_DtNl_is_multibyte)
155 return((char*) strtok_r(s1, s2, ptr));
158 * If this is the first call, save the string pointer, and bypass
159 * any leading separators.
162 *ptr = s1 + Dt_strspn(s1, s2);
164 /* A Null string pointer has no tokens */
168 /* Find out where the first terminator is */
169 if ((len = Dt_strcspn(*ptr, s2)) <= 0)
175 /* Keep track of where the token started */
178 /* Null out the terminator; we need to know how many bytes are
179 * occupied by the terminator, so that we can skip over it to
180 * the next character.
183 * We have to take care of the case when mblen() returns -1.
185 offset = mblen(*ptr + len, MB_CUR_MAX);
188 *(*ptr + len) = '\0';
189 *ptr += (len + offset);
192 * In preparation for the next pass, skip any other occurrances of
193 * the terminator characters which were joined with the terminator
194 * we first encountered.
196 len = Dt_strspn(*ptr, s2);
203 * Dt version of strspn(s1, s2).
204 * Returns the span of characters in s1 contained in s2.
205 * Only s1 can be multibyte.
213 wchar_t s1char, s2char;
220 /* Use the standard libc function, if multibyte is not present */
221 if (!_DtNl_is_multibyte)
222 return(strspn(s1, s2));
224 /* A Null string has no spans */
231 /* Extract the next character from s1; may be multibyte */
232 if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
237 * Compare this character against all the chars in s2. Keep
238 * working through s1, until a character is found in s1 which
239 * is not contained in s2.
245 /* Extract the next character from s2; cannot be multibyte */
248 /* If a match is found, keep processing s1 */
249 if (s1char == s2char)
258 * If we made it here because all of s2 was searched, and a match
259 * was not found against s1, then we are done.
270 * Dt version of strcspn(s1, s2).
271 * Returns the span of characters in s1 not contained in s2.
272 * Only s1 can be multibyte.
280 wchar_t s1char, s2char;
286 /* Use the standard libc function, if multibyte is not present */
287 if (!_DtNl_is_multibyte)
288 return(strcspn(s1, s2));
290 /* An empty string has no spans */
297 /* Extract the next character from s1; may be multibyte */
298 if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
303 * Compare this character against all the chars in s2. Keep
304 * working through s1, until a character is found in s1 which
305 * is contained in s2.
310 /* Extract the next character from s2; cannot be multibyte */
313 /* If a match occurs, then we are done */
314 if (s1char == s2char)
319 * If we've made it here, then we searched all of s2, and none of
320 * its components matched s1; continue with the next character
331 * Dt version of strchr(s, c).
332 * Returns a pointer to the first occurance of 'c' in 's'.
349 /* Use standard libc function if multibyte is not enabled */
350 if (!_DtNl_is_multibyte)
351 return(strchr(s, c));
359 /* Extract next char from 's'; may be multibyte */
360 if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
364 /* If we match 'c', then return a pointer to this character */
369 /* No match was found */
375 * Dt version of strrchr(s, c).
376 * Returns a pointer to the last occurance of 'c' in 's'.
394 /* Use standard libc function if multibyte is not enabled */
395 if (!_DtNl_is_multibyte)
396 return(strrchr(s, c));
404 /* Extract next char from 's'; may be multibyte */
405 if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
409 /* If we match 'c', keep track of it, and keep looking */
419 * Dt equivalent of s[strlen(s) - 1]
420 * Returns the last character in the string 's'.
431 if ((s == NULL) || (*s == '\0'))
438 /* Use the easy method, if possible */
439 if (!_DtNl_is_multibyte)
441 *cptr = s + strlen(s) - 1;
446 /* Move through the string, keeping a ptr to the last character found */
450 * We have to take care of the case when mbtowc() returns -1
452 len = mbtowc(NULL, s, MB_CUR_MAX);
458 /* Backup to the character before the NULL */
459 *lenptr = mblen(s-len, MB_CUR_MAX);
465 * Dt equivalent of strlen()
466 * Returns the number of characters (not bytes) in a string
479 if (!_DtNl_is_multibyte)
482 /* Move through the string, counting each character present */
485 len = mblen(s, MB_CUR_MAX);
486 /* if invalid character, still count it and continue */
496 /******************************************************************************
499 * return a pointer to the next multi-byte character after the character
500 * pointed to by "s". If "s" does not point to a valid multi-byte
501 * character advance one byte.
503 ******************************************************************************/
505 _Dt_NextChar(char *s)
509 if (_DtNl_is_multibyte || (MB_CUR_MAX > 1))
510 len = mblen ( s, MB_CUR_MAX);
513 * If "s" did not point to a vaild multi-byte character,
514 * move ahead one byte.
522 /******************************************************************************
524 * _Dt_PrevChar(start,s)
525 * return a pointer to the multi-byte character preceding the
526 * character pointed to by "s". If "s" does not point to a valid
527 * multi-byte character retreat one byte. "start" should point to
528 * a character preceding "s" in the multi-byte string.
530 ******************************************************************************/
532 _Dt_PrevChar(const char *start, char *s)
537 if ( !_DtNl_is_multibyte || (MB_CUR_MAX == 1) )
541 * Check if "*s" is a valid multi-byte character.
542 * if not just return the previous byte.
544 if ( mblen(s,MB_CUR_MAX) < 0 )
548 * "start" must be less than "s" ; if not return
555 * Check that "start" points to a valid multi-byte character.
556 * otherwise return "s-1"
558 if ( mblen(start,MB_CUR_MAX) < 0 )
562 * Starting from "start" traverse the string until we find
563 * the character preceding "s".
566 * We have to take care of the case when mblen() returns -1.
568 for (p = (char *)start;
569 p + (len = (mblen(p,MB_CUR_MAX) == -1 ? 1 : mblen(p,MB_CUR_MAX))) < s;
571 /* NULL STATEMENT */;
574 * We should always find a multi-byte character preceding "s" if
575 * "*s" is a valid multi-byte char and not the first character of
578 /* myassert(p < s); */
584 * Dt mult-byte equivalent of isspace()
589 if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
590 return isspace((u_char)*s);
592 if ( mblen(s,MB_CUR_MAX) == 1 )
593 return isspace((u_char)*s);
599 * Dt mult-byte equivalent of isdigit()
604 if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
607 if ( mblen(s,MB_CUR_MAX) == 1 )
617 * Dt equivalent of &(s[n])
618 * Returns a pointer to the indicated character
629 if ((s == NULL) || (n < 0) || (n > Dt_charCount(s)))
633 while ((count < n) && (*s))
635 if (_DtNl_is_multibyte)
636 len = mblen(s, MB_CUR_MAX);
640 * We have to take care of the case when mblen() returns -1.
654 * multibyte version of strpbrk().
655 * Only cs can be multibyte.
666 return(strpbrk(cs, ct));
669 len = mblen(cs, MB_CUR_MAX);
673 for(i = 0; i < strlen(ct); i++) {
685 * returns 1 if a character before s2 in s1 is single-byte,
686 * returns 0 if it is multi-byte.
705 n = mblen(s1, MB_CUR_MAX) > 1 ? mblen(s1, MB_CUR_MAX) : 1;
718 if ((s == NULL) || (n < 0) || (n > strlen(s)))
729 return(strpbrk(cs, ct));