123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $TOG: DtNlUtils.c /main/10 1999/10/15 12:07:23 mgreess $ */
- /*
- * (c) Copyright 1993, 1994 Hewlett-Packard Company *
- * (c) Copyright 1993, 1994 International Business Machines Corp. *
- * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
- * (c) Copyright 1993, 1994 Novell, Inc. *
- */
- /*****************************************************************************/
- /* */
- /* This file contains the Dt versions of common string functions, which */
- /* have not yet been provided by the HP-UX platform. */
- /* These functions know how to handle multi-byte strings. */
- /* */
- /*****************************************************************************/
- #include <ctype.h>
- #include <string.h>
- #include <Dt/DtNlUtils.h>
- #include "DtSvcLock.h"
- /*
- * Globals
- */
- Boolean _DtNl_is_multibyte = False;
- #ifdef NLS16
- /*
- * Dt nls initialization function.
- * will see if multibyte characters are
- * supported for the locale. If multibyte characters are not supported,
- * then all of our string utilites simply call the standard libc function.
- */
- void
- Dt_nlInit( void )
- {
- char * bc;
- static Boolean first = True;
- _DtSvcProcessLock();
- if (!first) {
- _DtSvcProcessUnlock();
- return;
- }
- first = False;
- _DtSvcProcessUnlock();
- if (MB_CUR_MAX > 1)
- _DtNl_is_multibyte = True;
- else
- _DtNl_is_multibyte = False;
- }
- /*
- * Dt version of strtok(s1, s2).
- * Returns a pointer to the span of characters in s1 terminated by
- * one of the characters in s2. Only s1 can be multibyte.
- */
- char *
- Dt_strtok(
- char *s1,
- char *s2 )
- {
- static char *ptr;
- char * return_ptr;
- int len;
- int offset;
- /* Use standard libc function, if no multibyte */
- if (!_DtNl_is_multibyte)
- return(strtok(s1, s2));
- /*
- * If this is the first call, save the string pointer, and bypass
- * any leading separators.
- */
- if (s1)
- ptr = s1 + Dt_strspn(s1, s2);
- /* A Null string pointer has no tokens */
- if (ptr == NULL)
- return(NULL);
- /* Find out where the first terminator is */
- if ((len = Dt_strcspn(ptr, s2)) <= 0)
- {
- /* No tokens left */
- return(NULL);
- }
- /* Keep track of where the token started */
- return_ptr = ptr;
- /* Null out the terminator; we need to know how many bytes are
- * occupied by the terminator, so that we can skip over it to
- * the next character.
- */
- /*
- * We have to take care of the case when mblen() returns -1.
- */
- offset = mblen(ptr + len, MB_CUR_MAX);
- if( offset == -1 )
- offset = 1;
- *(ptr + len) = '\0';
- ptr += (len + offset);
- /*
- * In preparation for the next pass, skip any other occurrences of
- * the terminator characters which were joined with the terminator
- * we first encountered.
- */
- len = Dt_strspn(ptr, s2);
- ptr += len;
- return(return_ptr);
- }
- char *
- Dt_strtok_r(
- char *s1,
- char *s2,
- char **ptr )
- {
- char * return_ptr;
- int len;
- int offset;
- /* Use standard libc function, if no multibyte */
- if (!_DtNl_is_multibyte)
- return((char*) strtok_r(s1, s2, ptr));
- /*
- * If this is the first call, save the string pointer, and bypass
- * any leading separators.
- */
- if (s1)
- *ptr = s1 + Dt_strspn(s1, s2);
- /* A Null string pointer has no tokens */
- if (*ptr == NULL)
- return(NULL);
- /* Find out where the first terminator is */
- if ((len = Dt_strcspn(*ptr, s2)) <= 0)
- {
- /* No tokens left */
- return(NULL);
- }
- /* Keep track of where the token started */
- return_ptr = *ptr;
- /* Null out the terminator; we need to know how many bytes are
- * occupied by the terminator, so that we can skip over it to
- * the next character.
- */
- /*
- * We have to take care of the case when mblen() returns -1.
- */
- offset = mblen(*ptr + len, MB_CUR_MAX);
- if( offset == -1 )
- offset = 1;
- *(*ptr + len) = '\0';
- *ptr += (len + offset);
- /*
- * In preparation for the next pass, skip any other occurrences of
- * the terminator characters which were joined with the terminator
- * we first encountered.
- */
- len = Dt_strspn(*ptr, s2);
- *ptr += len;
- return(return_ptr);
- }
- /*
- * Dt version of strspn(s1, s2).
- * Returns the span of characters in s1 contained in s2.
- * Only s1 can be multibyte.
- */
- int
- Dt_strspn(
- char *s1,
- char *s2 )
- {
- wchar_t s1char, s2char;
- int s1len, s2len;
- int i;
- int count;
- char * ptr;
- Boolean match;
- /* Use the standard libc function, if multibyte is not present */
- if (!_DtNl_is_multibyte)
- return(strspn(s1, s2));
- /* A Null string has no spans */
- if (s1 == NULL)
- return(0);
- count = 0;
- while (*s1)
- {
- /* Extract the next character from s1; may be multibyte */
- if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
- return(0);
- s1 += s1len;
- /*
- * Compare this character against all the chars in s2. Keep
- * working through s1, until a character is found in s1 which
- * is not contained in s2.
- */
- ptr = s2;
- match = False;
- while (*ptr)
- {
- /* Extract the next character from s2; cannot be multibyte */
- s2char = *ptr++;
- /* If a match is found, keep processing s1 */
- if (s1char == s2char)
- {
- match = True;
- count += s1len;
- break;
- }
- }
- /*
- * If we made it here because all of s2 was searched, and a match
- * was not found against s1, then we are done.
- */
- if (!match)
- return(count);
- }
- return(count);
- }
- /*
- * Dt version of strcspn(s1, s2).
- * Returns the span of characters in s1 not contained in s2.
- * Only s1 can be multibyte.
- */
- int
- Dt_strcspn(
- char *s1,
- char *s2 )
- {
- wchar_t s1char, s2char;
- int s1len, s2len;
- int i;
- int count;
- char * ptr;
- /* Use the standard libc function, if multibyte is not present */
- if (!_DtNl_is_multibyte)
- return(strcspn(s1, s2));
- /* An empty string has no spans */
- if (s1 == NULL)
- return(0);
- count = 0;
- while (*s1)
- {
- /* Extract the next character from s1; may be multibyte */
- if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
- return(0);
- s1 += s1len;
- /*
- * Compare this character against all the chars in s2. Keep
- * working through s1, until a character is found in s1 which
- * is contained in s2.
- */
- ptr = s2;
- while (*ptr)
- {
- /* Extract the next character from s2; cannot be multibyte */
- s2char = *ptr++;
-
- /* If a match occurs, then we are done */
- if (s1char == s2char)
- return(count);
- }
- /*
- * If we've made it here, then we searched all of s2, and none of
- * its components matched s1; continue with the next character
- * in s1.
- */
- count += s1len;
- }
- return(count);
- }
- /*
- * Dt version of strchr(s, c).
- * Returns a pointer to the first occurrence of 'c' in 's'.
- */
- char *
- Dt_strchr(
- char *s,
- char c )
- {
- wchar_t schar;
- int i;
- int slen;
- wchar_t wc;
- char foo[2];
- if (s == NULL)
- return(NULL);
- /* Use standard libc function if multibyte is not enabled */
- if (!_DtNl_is_multibyte)
- return(strchr(s, c));
- foo[0] = c;
- foo[1] = '\0';
- mbtowc(&wc, foo, 2);
- do
- {
- /* Extract next char from 's'; may be multibyte */
- if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
- return(NULL);
- s += slen;
- /* If we match 'c', then return a pointer to this character */
- if (schar == wc)
- return (s - slen);
- } while (slen > 0);
- /* No match was found */
- return(NULL);
- }
- /*
- * Dt version of strrchr(s, c).
- * Returns a pointer to the last occurrence of 'c' in 's'.
- */
- char *
- Dt_strrchr(
- char *s,
- char c )
- {
- wchar_t schar;
- int i;
- int slen;
- char * last = NULL;
- wchar_t wc;
- char foo[2];
- if (s == NULL)
- return(NULL);
- /* Use standard libc function if multibyte is not enabled */
- if (!_DtNl_is_multibyte)
- return(strrchr(s, c));
- foo[0] = c;
- foo[1] = '\0';
- mbtowc(&wc, foo, 2);
- do
- {
- /* Extract next char from 's'; may be multibyte */
- if ((slen = mbtowc(&schar, s, MB_CUR_MAX)) < 0)
- return(NULL);
- s += slen;
- /* If we match 'c', keep track of it, and keep looking */
- if (schar == wc)
- last = s - slen;
- } while (slen > 0);
- return(last);
- }
- /*
- * Dt equivalent of s[strlen(s) - 1]
- * Returns the last character in the string 's'.
- */
- void
- Dt_lastChar(
- char *s,
- char **cptr,
- int *lenptr )
- {
- int len = 0;
- if ((s == NULL) || (*s == '\0'))
- {
- *lenptr = 0;
- *cptr = NULL;
- return;
- }
- /* Use the easy method, if possible */
- if (!_DtNl_is_multibyte)
- {
- *cptr = s + strlen(s) - 1;
- *lenptr = 1;
- return;
- }
- /* Move through the string, keeping a ptr to the last character found */
- while (*s)
- {
- /*
- * We have to take care of the case when mbtowc() returns -1
- */
- len = mbtowc(NULL, s, MB_CUR_MAX);
- if ( len == -1 )
- len = 1;
- s += len;
- }
- /* Backup to the character before the NULL */
- *lenptr = mblen(s-len, MB_CUR_MAX);
- *cptr = s - len;
- }
- /*
- * Dt equivalent of strlen()
- * Returns the number of characters (not bytes) in a string
- */
- int
- Dt_charCount(
- char *s )
- {
- int count = 0;
- int len;
- if (s == NULL)
- return(0);
- if (!_DtNl_is_multibyte)
- return(strlen(s));
- /* Move through the string, counting each character present */
- while (*s)
- {
- len = mblen(s, MB_CUR_MAX);
- /* if invalid character, still count it and continue */
- if (len == -1)
- len = 1;
- s += len;
- count++;
- }
- return(count);
- }
- /******************************************************************************
- *
- * _Dt_NextChar(s)
- * return a pointer to the next multi-byte character after the character
- * pointed to by "s". If "s" does not point to a valid multi-byte
- * character advance one byte.
- *
- ******************************************************************************/
- char *
- _Dt_NextChar(char *s)
- {
- int len=1;
-
- if (_DtNl_is_multibyte || (MB_CUR_MAX > 1))
- len = mblen ( s, MB_CUR_MAX);
- /*
- * If "s" did not point to a vaild multi-byte character,
- * move ahead one byte.
- */
- if ( len == -1 )
- len = 1;
- return s + len;
- }
- /******************************************************************************
- *
- * _Dt_PrevChar(start,s)
- * return a pointer to the multi-byte character preceding the
- * character pointed to by "s". If "s" does not point to a valid
- * multi-byte character retreat one byte. "start" should point to
- * a character preceding "s" in the multi-byte string.
- *
- ******************************************************************************/
- char *
- _Dt_PrevChar(const char *start, char *s)
- {
- char *p;
- int len;
- if ( !_DtNl_is_multibyte || (MB_CUR_MAX == 1) )
- return (s - 1);
- /*
- * Check if "*s" is a valid multi-byte character.
- * if not just return the previous byte.
- */
- if ( mblen(s,MB_CUR_MAX) < 0 )
- return (s - 1);
- /*
- * "start" must be less than "s" ; if not return
- * (s-1)
- */
- if ( start >= s )
- return (s - 1);
-
- /*
- * Check that "start" points to a valid multi-byte character.
- * otherwise return "s-1"
- */
- if ( mblen(start,MB_CUR_MAX) < 0 )
- return (s-1);
- /*
- * Starting from "start" traverse the string until we find
- * the character preceding "s".
- */
- /*
- * We have to take care of the case when mblen() returns -1.
- */
- for (p = (char *)start;
- p + (len = (mblen(p,MB_CUR_MAX) == -1 ? 1 : mblen(p,MB_CUR_MAX))) < s;
- p += len)
- /* NULL STATEMENT */;
- /*
- * We should always find a multi-byte character preceding "s" if
- * "*s" is a valid multi-byte char and not the first character of
- * the text.
- */
- /* myassert(p < s); */
-
- return p;
- }
- /*
- * Dt mult-byte equivalent of isspace()
- */
- int
- _Dt_isspace(char *s)
- {
- if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
- return isspace((u_char)*s);
- if ( mblen(s,MB_CUR_MAX) == 1 )
- return isspace((u_char)*s);
- else
- return 0;
- }
- /*
- * Dt mult-byte equivalent of isdigit()
- */
- int
- _Dt_isdigit(char *s)
- {
- if ( !_DtNl_is_multibyte || MB_CUR_MAX == 1 )
- return isdigit(*s);
- if ( mblen(s,MB_CUR_MAX) == 1 )
- return isdigit(*s);
- else
- return 0;
- }
- /*
- * Dt equivalent of &(s[n])
- * Returns a pointer to the indicated character
- */
- char *
- _DtGetNthChar(
- char *s,
- int n )
- {
- int count;
- int len;
- if ((s == NULL) || (n < 0) || (n > Dt_charCount(s)))
- return(NULL);
- count = 0;
- while ((count < n) && (*s))
- {
- if (_DtNl_is_multibyte)
- len = mblen(s, MB_CUR_MAX);
- else
- len = 1;
- /*
- * We have to take care of the case when mblen() returns -1.
- */
- if ( len == -1 )
- len = 1;
- s += len;
- count++;
- }
- return(s);
- }
- /*
- * multibyte version of strpbrk().
- * Only cs can be multibyte.
- */
- char *
- _dt_strpbrk(
- char *cs,
- char *ct)
- {
- int len;
- size_t i;
- if(MB_CUR_MAX == 1)
- return(strpbrk(cs, ct));
- while(*cs) {
- len = mblen(cs, MB_CUR_MAX);
- if(len < 1)
- len = 1;
- if(len == 1) {
- for(i = 0; i < strlen(ct); i++) {
- if(*cs == *(ct + i))
- return(cs);
- }
- }
- cs += len;
- }
- return(NULL);
- }
- /*
- * returns 1 if a character before s2 in s1 is single-byte,
- * returns 0 if it is multi-byte.
- */
- int
- _is_previous_single(
- char *s1,
- char *s2)
- {
- int n = 1;
- if(MB_CUR_MAX == 1)
- return(1);
- while(*s1) {
- if(s1 == s2) {
- if(n > 1)
- return(0);
- else
- return(1);
- }
- n = mblen(s1, MB_CUR_MAX) > 1 ? mblen(s1, MB_CUR_MAX) : 1;
- s1 += n;
- }
- return(1);
- }
- #else
- char *
- _DtGetNthChar(
- char *s,
- int n )
- {
- if ((s == NULL) || (n < 0) || (n > strlen(s)))
- return(NULL);
- return (s + n);
- }
- char *
- _dt_strpbrk(
- char *cs,
- char *ct)
- {
- return(strpbrk(cs, ct));
- }
- int
- _is_previous_single(
- char *s1,
- char *s2)
- {
- return(1);
- }
- #endif /* NLS16 */
|