/* * 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 librararies 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 #include
#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 occurrances 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 occurrances 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 occurance 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 occurance 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 */