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 libraries 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 /*****************************************************************************/
40 #include <Dt/DtNlUtils.h>
41 #include "DtSvcLock.h"
46 Boolean _DtNl_is_multibyte = False;
51 * Dt nls initialization function.
52 * will see if multibyte characters are
53 * supported for the locale. If multibyte characters are not supported,
54 * then all of our string utilites simply call the standard libc function.
61 static Boolean first = True;
65 _DtSvcProcessUnlock();
70 _DtSvcProcessUnlock();
73 _DtNl_is_multibyte = True;
75 _DtNl_is_multibyte = False;
79 * Dt version of strtok(s1, s2).
80 * Returns a pointer to the span of characters in s1 terminated by
81 * one of the characters in s2. Only s1 can be multibyte.
94 /* Use standard libc function, if no multibyte */
95 if (!_DtNl_is_multibyte)
96 return(strtok(s1, s2));
99 * If this is the first call, save the string pointer, and bypass
100 * any leading separators.
103 ptr = s1 + Dt_strspn(s1, s2);
105 /* A Null string pointer has no tokens */
109 /* Find out where the first terminator is */
110 if ((len = Dt_strcspn(ptr, s2)) <= 0)
116 /* Keep track of where the token started */
119 /* Null out the terminator; we need to know how many bytes are
120 * occupied by the terminator, so that we can skip over it to
121 * the next character.
124 * We have to take care of the case when mblen() returns -1.
126 offset = mblen(ptr + len, MB_CUR_MAX);
130 ptr += (len + offset);
133 * In preparation for the next pass, skip any other occurrences of
134 * the terminator characters which were joined with the terminator
135 * we first encountered.
137 len = Dt_strspn(ptr, s2);
154 /* Use standard libc function, if no multibyte */
155 if (!_DtNl_is_multibyte)
156 return((char*) strtok_r(s1, s2, ptr));
159 * If this is the first call, save the string pointer, and bypass
160 * any leading separators.
163 *ptr = s1 + Dt_strspn(s1, s2);
165 /* A Null string pointer has no tokens */
169 /* Find out where the first terminator is */
170 if ((len = Dt_strcspn(*ptr, s2)) <= 0)
176 /* Keep track of where the token started */
179 /* Null out the terminator; we need to know how many bytes are
180 * occupied by the terminator, so that we can skip over it to
181 * the next character.
184 * We have to take care of the case when mblen() returns -1.
186 offset = mblen(*ptr + len, MB_CUR_MAX);
189 *(*ptr + len) = '\0';
190 *ptr += (len + offset);
193 * In preparation for the next pass, skip any other occurrences of
194 * the terminator characters which were joined with the terminator
195 * we first encountered.
197 len = Dt_strspn(*ptr, s2);
204 * Dt version of strspn(s1, s2).
205 * Returns the span of characters in s1 contained in s2.
206 * Only s1 can be multibyte.
214 wchar_t s1char, s2char;
221 /* Use the standard libc function, if multibyte is not present */
222 if (!_DtNl_is_multibyte)
223 return(strspn(s1, s2));
225 /* A Null string has no spans */
232 /* Extract the next character from s1; may be multibyte */
233 if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
238 * Compare this character against all the chars in s2. Keep
239 * working through s1, until a character is found in s1 which
240 * is not contained in s2.
246 /* Extract the next character from s2; cannot be multibyte */
249 /* If a match is found, keep processing s1 */
250 if (s1char == s2char)
259 * If we made it here because all of s2 was searched, and a match
260 * was not found against s1, then we are done.
271 * Dt version of strcspn(s1, s2).
272 * Returns the span of characters in s1 not contained in s2.
273 * Only s1 can be multibyte.
281 wchar_t s1char, s2char;
287 /* Use the standard libc function, if multibyte is not present */
288 if (!_DtNl_is_multibyte)
289 return(strcspn(s1, s2));
291 /* An empty string has no spans */
298 /* Extract the next character from s1; may be multibyte */
299 if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
304 * Compare this character against all the chars in s2. Keep
305 * working through s1, until a character is found in s1 which
306 * is contained in s2.
311 /* Extract the next character from s2; cannot be multibyte */
314 /* If a match occurs, then we are done */
315 if (s1char == s2char)
320 * If we've made it here, then we searched all of s2, and none of
321 * its components matched s1; continue with the next character
332 * Dt version of strchr(s, c).
333 * Returns a pointer to the first occurrence of 'c' in 's'.
350 /* Use standard libc function if multibyte is not enabled */
351 if (!_DtNl_is_multibyte)
352 return(strchr(s, c));
360 /* Extract next char from 's'; may be multibyte */
361 if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
365 /* If we match 'c', then return a pointer to this character */
370 /* No match was found */
376 * Dt version of strrchr(s, c).
377 * Returns a pointer to the last occurrence of 'c' in 's'.
395 /* Use standard libc function if multibyte is not enabled */
396 if (!_DtNl_is_multibyte)
397 return(strrchr(s, c));
405 /* Extract next char from 's'; may be multibyte */
406 if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
410 /* If we match 'c', keep track of it, and keep looking */
420 * Dt equivalent of s[strlen(s) - 1]
421 * Returns the last character in the string 's'.
432 if ((s == NULL) || (*s == '\0'))
439 /* Use the easy method, if possible */
440 if (!_DtNl_is_multibyte)
442 *cptr = s + strlen(s) - 1;
447 /* Move through the string, keeping a ptr to the last character found */
451 * We have to take care of the case when mbtowc() returns -1
453 len = mbtowc(NULL, s, MB_CUR_MAX);
459 /* Backup to the character before the NULL */
460 *lenptr = mblen(s-len, MB_CUR_MAX);
466 * Dt equivalent of strlen()
467 * Returns the number of characters (not bytes) in a string
480 if (!_DtNl_is_multibyte)
483 /* Move through the string, counting each character present */
486 len = mblen(s, MB_CUR_MAX);
487 /* if invalid character, still count it and continue */
497 /******************************************************************************
500 * return a pointer to the next multi-byte character after the character
501 * pointed to by "s". If "s" does not point to a valid multi-byte
502 * character advance one byte.
504 ******************************************************************************/
506 _Dt_NextChar(char *s)
510 if (_DtNl_is_multibyte || (MB_CUR_MAX > 1))
511 len = mblen ( s, MB_CUR_MAX);
514 * If "s" did not point to a vaild multi-byte character,
515 * move ahead one byte.
523 /******************************************************************************
525 * _Dt_PrevChar(start,s)
526 * return a pointer to the multi-byte character preceding the
527 * character pointed to by "s". If "s" does not point to a valid
528 * multi-byte character retreat one byte. "start" should point to
529 * a character preceding "s" in the multi-byte string.
531 ******************************************************************************/
533 _Dt_PrevChar(const char *start, char *s)
538 if ( !_DtNl_is_multibyte || (MB_CUR_MAX == 1) )
542 * Check if "*s" is a valid multi-byte character.
543 * if not just return the previous byte.
545 if ( mblen(s,MB_CUR_MAX) < 0 )
549 * "start" must be less than "s" ; if not return
556 * Check that "start" points to a valid multi-byte character.
557 * otherwise return "s-1"
559 if ( mblen(start,MB_CUR_MAX) < 0 )
563 * Starting from "start" traverse the string until we find
564 * the character preceding "s".
567 * We have to take care of the case when mblen() returns -1.
569 for (p = (char *)start;
570 p + (len = (mblen(p,MB_CUR_MAX) == -1 ? 1 : mblen(p,MB_CUR_MAX))) < s;
572 /* NULL STATEMENT */;
575 * We should always find a multi-byte character preceding "s" if
576 * "*s" is a valid multi-byte char and not the first character of
579 /* myassert(p < s); */
585 * Dt mult-byte equivalent of isspace()
590 if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
591 return isspace((u_char)*s);
593 if ( mblen(s,MB_CUR_MAX) == 1 )
594 return isspace((u_char)*s);
600 * Dt mult-byte equivalent of isdigit()
605 if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
608 if ( mblen(s,MB_CUR_MAX) == 1 )
618 * Dt equivalent of &(s[n])
619 * Returns a pointer to the indicated character
630 if ((s == NULL) || (n < 0) || (n > Dt_charCount(s)))
634 while ((count < n) && (*s))
636 if (_DtNl_is_multibyte)
637 len = mblen(s, MB_CUR_MAX);
641 * We have to take care of the case when mblen() returns -1.
655 * multibyte version of strpbrk().
656 * Only cs can be multibyte.
667 return(strpbrk(cs, ct));
670 len = mblen(cs, MB_CUR_MAX);
674 for(i = 0; i < strlen(ct); i++) {
686 * returns 1 if a character before s2 in s1 is single-byte,
687 * returns 0 if it is multi-byte.
706 n = mblen(s1, MB_CUR_MAX) > 1 ? mblen(s1, MB_CUR_MAX) : 1;
719 if ((s == NULL) || (n < 0) || (n > strlen(s)))
730 return(strpbrk(cs, ct));