123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149 |
- /*
- * 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: StringFuncs.c /main/15 1998/03/19 09:49:44 mgreess $ */
- /************************************<+>*************************************
- ****************************************************************************
- **
- ** File: StringFuncs.c
- **
- ** Project: Cde DtHelp
- **
- ** Description: Semi private string functions - can be platform dependent.
- **
- **
- ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
- **
- ** (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.
- **
- **
- **
- ****************************************************************************
- ************************************<+>*************************************/
- #ifdef HAVE_CONFIG_H
- #include <cde_config.h>
- #endif
- /*
- * system includes
- */
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include <errno.h>
- #include <locale.h> /* getlocale(), LOCALE_STATUS, LC_xxx */
- #if defined(_AIX) || defined(CSRG_BASED) || defined(__linux__)
- #include <ctype.h>
- #endif
- #include "CvStringI.h" /* for string functions used by Canvas Engine */
- #include "StringFuncsI.h" /* for _CEStrcollProc */
- /* JET: This was if !defined(linux), which is wrong. We should use the
- * real deal on linux too */
- #include <iconv.h>
- #if 0
- # define iconv_t int
- # define iconv_open(a, b) ((iconv_t) -1)
- # define iconv(a, b, c, d, e) ((size_t) 0)
- # define iconv_close(a) (0)
- #endif
- #define ICONV_INBUF_TYPE ICONV_CONST char **
- /**** Types ****/
- /* Private structure of the IconvContext. Public
- structure doesn't reveal implementation. */
- typedef struct _DtHelpCeIconvContextRec
- {
- iconv_t cd;
- int tableSize;
- unsigned char * table; /* translation table */
- char * fromCodeset;
- char * toCodeset;
- } _DtHelpCeIconvContextRec;
- #ifndef True
- #define True 1
- #endif
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef False
- #define False 0
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- /******************************************************************************
- *
- * Private variables and defines.
- *
- *****************************************************************************/
- #define EOS '\0'
- /******************************************************************************
- *
- * Semi Public Functions
- *
- *****************************************************************************/
- /******************************************************************************
- * Function: _DtHelpCeStrcspn (const char *s1, const char *s2, max_len, &ret_len)
- *
- * Returns in 'ret_len' the length of the initial segment of string
- * s1 which consists entirely of characters not found in string s2.
- *
- * Returns:
- * -1 If found an invalid character.
- * 0 If found a character in string s2
- * 1 If found the null byte character.
- *****************************************************************************/
- int
- _DtHelpCeStrcspn (
- const char *s1,
- const char *s2,
- int max_len,
- int *ret_len )
- {
- int len;
- int len2;
- const char *p1;
- const char *p2;
- if (!s1)
- {
- *ret_len = 0;
- return 0;
- }
- if (*s1 == '\0')
- {
- *ret_len = 0;
- return 1;
- }
- if (!s2 || *s2 == '\0')
- {
- *ret_len = strlen (s1);
- return 1;
- }
- if (max_len == 1)
- {
- /*
- * no need to go through any hassle, just use the 3C function
- */
- *ret_len = strcspn (s1, s2);
- if (s1[*ret_len] == '\0')
- return 1;
- return 0;
- }
- p1 = s1;
- while (*p1 != '\0')
- {
- len = mblen (p1, max_len);
- if (len == -1)
- {
- /*
- * we found an invalid character
- * return the length found so far and the flag.
- */
- *ret_len = p1 - s1;
- return -1;
- }
- p2 = s2;
- while (*p2 != '\0')
- {
- len2 = mblen (p2, max_len);
- if (len2 == -1)
- len2 = 1;
- if (len2 == len && strncmp (p1, p2, len) == 0)
- {
- *ret_len = p1 - s1;
- return 0;
- }
- p2 += len2;
- }
- p1 += len;
- }
- *ret_len = p1 - s1;
- return 1;
- }
- /******************************************************************************
- * Function: _DtHelpCeStrspn (const char *s1, const char *s2, max_len, &ret_len)
- *
- * Returns in 'ret_len' the length of the initial segment of string
- * s1 which consists entirely of characters found in string s2.
- *
- * Returns:
- * -1 If found an invalid character.
- * 0 If found a character not in string s2
- * 1 If found the null byte character.
- *****************************************************************************/
- int
- _DtHelpCeStrspn (
- char *s1,
- char *s2,
- int max_len,
- int *ret_len )
- {
- int len;
- int len2;
- char *p1;
- char *p2;
- char found;
- if (!s1 || !s2 || *s2 == '\0')
- {
- *ret_len = 0;
- return 0;
- }
- if (*s1 == '\0')
- {
- *ret_len = 0;
- return 1;
- }
- if (max_len == 1)
- {
- /*
- * no need to go through any hassle, just use the 3C function
- */
- *ret_len = strspn (s1, s2);
- if (s1[*ret_len] == '\0')
- return 1;
- return 0;
- }
- p1 = s1;
- found = True;
- while (*p1 != '\0' && found)
- {
- len = mblen (p1, max_len);
- if (len == -1)
- {
- /*
- * we found an invalid character
- * return the length found so far and the flag.
- */
- *ret_len = p1 - s1;
- return -1;
- }
- p2 = s2;
- found = False;
- while (*p2 != '\0' && !found)
- {
- len2 = mblen (p2, max_len);
- if (len2 == -1)
- len2 = 1;
- if (len2 == len && strncmp (p1, p2, len) == 0)
- found = True;
- p2 += len2;
- }
- if (found)
- p1 += len;
- }
- *ret_len = p1 - s1;
- if (found)
- return 1;
- return 0;
- }
- /******************************************************************************
- * Function: _DtHelpCeStrchr (char *s1, char *value, max_len, ret_ptr)
- *
- * Returns in 'ret_ptr' the address of the first occurence of 'value'
- * in string s1.
- *
- * Returns:
- * -1 If found an invalid character.
- * 0 If found value in string s2
- * 1 If found the null byte character without finding 'value'.
- * 'ret_ptr' will also be null in this case.
- *****************************************************************************/
- int
- _DtHelpCeStrchr (
- const char *s1,
- const char *value,
- int max_len,
- char **ret_ptr )
- {
- int len;
- int valLen;
- const char *p1;
- *ret_ptr = NULL;
- if (s1 == NULL || *s1 == '\0')
- return 1;
- if (max_len == 1)
- {
- *ret_ptr = strchr (s1, ((int)*value));
- if (*ret_ptr)
- return 0;
- return 1;
- }
- p1 = s1;
- valLen = mblen(value, max_len);
- if (valLen < 1)
- return -1;
- while (*p1 != '\0')
- {
- len = mblen (p1, max_len);
- if (len == -1)
- return -1;
- if (len == valLen && strncmp(p1, value, len) == 0)
- {
- *ret_ptr = (char *)p1;
- return 0;
- }
- p1 += len;
- }
- return 1;
- }
- /******************************************************************************
- * Function: _DtHelpCeStrrchr (char *s1, char *value, max_len, ret_ptr)
- *
- * Returns in 'ret_ptr' the address of the last occurence of 'value'
- * in string s1.
- *
- * Returns:
- * -1 If found an invalid character.
- * 0 If found value in string s2
- * 1 If found the null byte character without finding 'value'.
- * 'ret_ptr' will also be null in this case.
- *****************************************************************************/
- int
- _DtHelpCeStrrchr (
- const char *s1,
- const char *value,
- int max_len,
- char **ret_ptr )
- {
- int len;
- int valLen;
- const char *p1;
- *ret_ptr = NULL;
- if (s1 == NULL || *s1 == '\0')
- return 1;
- if (max_len == 1)
- {
- *ret_ptr = strrchr (s1, ((int)*value));
- if (*ret_ptr != NULL)
- return 0;
- return 1;
- }
- p1 = s1;
- valLen = mblen(value, max_len);
- if (valLen < 1)
- return -1;
- while (*p1 != '\0')
- {
- len = mblen (p1, max_len);
- if (len == -1)
- return -1;
- if (len == valLen && strncmp(p1, value, len) == 0)
- *ret_ptr = (char *)p1;
- p1 += len;
- }
- if (*ret_ptr != NULL)
- return 0;
- return 1;
- }
- /******************************************************************************
- * Function: _DtHelpCeCountChars (char *s1, max_len, ret_len)
- *
- * Returns in 'ret_len' the number of characters (not bytes)
- * in string s1.
- *
- * Returns:
- * -1 If found an invalid character. 'ret_len' contains the
- * number of 'good' characters found.
- * 0 If successful.
- *****************************************************************************/
- int
- _DtHelpCeCountChars (
- char *s1,
- int max_len,
- int *ret_len )
- {
- int len;
- *ret_len = 0;
- if (s1)
- {
- if (max_len == 1)
- *ret_len = strlen (s1);
- else
- {
- while (*s1)
- {
- len = mblen (s1, max_len);
- if (len == -1)
- return -1;
- *ret_len = *ret_len + 1;
- s1 += len;
- }
- }
- }
- return 0;
- }
- /*****************************************************************************
- * Function: _DtHelpCeUpperCase
- *
- * Parameters: string Specifies the string to change into
- * upper case.
- *
- * Return Value: Nothing
- *
- * Purpose: To change all lower case characters into upper case.
- *
- *****************************************************************************/
- void
- _DtHelpCeUpperCase ( char *string )
- {
- int len;
- if (string)
- {
- while (*string != '\0')
- {
- len = mblen (string, MB_CUR_MAX);
- if (len == 1)
- {
- *string = (unsigned char) toupper (*(unsigned char *)string);
- string++;
- }
- else if (len > 0)
- string += len;
- else
- return;
- }
- }
- }
- /************************************************************************
- * Function: _DtHelpCeStrHashToKey
- *
- * Parameters: C-format string to hash
- *
- * Purpose:
- * Does a very simple hash operation on the string and returns the value
- *
- * Returns: hash value
- *
- ************************************************************************/
- int _DtHelpCeStrHashToKey(
- const char * str)
- {
- char c;
- const char * tstr;
- int key = 0;
- if (!str) return 0; /* RETURN */
- for (tstr = str; (c = *tstr++); )
- key = (key << 1) + c;
- return key;
- }
- /******************************************************************************
- * Function: _DtHelpCeGetStrcollProc
- *
- * Parameters: none
- *
- * Returns: Ptr to the proper collation function to use
- * If the codeset of the locale is "C", then it is
- * strcasecmp(). If it's not, then it is strcoll().
- *
- * Purpose: When the codeset of the locale "C", strcoll()
- * performs collation identical to strcmp(), which is
- * strictly bitwise.
- *
- * To get case-insensitive collation, you need to use
- * strcasecmp() instead. If codeset != "C", then
- * strcoll() collates according to the language
- * setting.
- *
- * Warning: This code is not multi-thread safe. The multi-thread
- * safe setlocale must be used instead to make it so.
- *
- *****************************************************************************/
- _CEStrcollProc _DtHelpCeGetStrcollProc(void)
- {
- int Clang = 0;
- char * locale;
- extern int strcoll(const char *,const char *);
- #if defined(_AIX)
- extern int _DtHelpCeStrCaseCmp(const char *,const char *);
- #else
- extern int strcasecmp(const char *,const char *);
- #endif
- #define C_LANG "C"
- /* if locale is C, use the explicit case insensitive compare */
- locale = setlocale(LC_COLLATE,NULL); /* put locale in buf */
- if (strcmp(locale,C_LANG) == 0)
- Clang = 1;
- if (Clang)
- #if defined(_AIX)
- return _DtHelpCeStrCaseCmp;
- #else
- return strcasecmp;
- #endif
- return strcoll;
- }
- /*****************************************************************************
- * Function: String _DtHelpCeStripSpaces (string)
- *
- *
- * Parameters: String to process
- *
- * Return Value: Processed string
- *
- * Purpose: Strip all leading and trailing spaces.
- * Processing is in place
- *
- *****************************************************************************/
- char * _DtHelpCeStripSpaces (
- char * string)
- {
- int i;
- int multiLen = MB_CUR_MAX;
- char * space;
- if (string == NULL)
- return (string);
- /* Strip off leading spaces first */
- i = 0;
- while ((multiLen == 1 || (mblen(string + i, MB_LEN_MAX) == 1)) &&
- isspace((unsigned char) string[i]))
- {
- i++;
- }
- /* Copy over the leading spaces */
- strcpy(string, string + i);
- /* Drop out, if the string is now empty */
- if ((i = strlen(string) - 1) < 0)
- return(string);
- /* Strip off trailing spaces */
- if (multiLen == 1)
- {
- /* No multibyte; simply work back through the string */
- while ((i >= 0) && (isspace((unsigned char) string[i])))
- i--;
- string[i + 1] = '\0';
- }
- else
- {
- /* Work forward, looking for a trailing space of spaces */
- int len;
- i = 0;
- space = NULL;
- while (string[i])
- {
- if ( ((len =mblen(string + i, MB_LEN_MAX)) == 1)
- && isspace((unsigned char) string[i]))
- {
- /* Found a space */
- if (space == NULL)
- space = string + i;
- }
- else if (space)
- space = NULL;
- /* if there is an invalid character, treat as a valid one-byte */
- if (len == -1)
- len = 1;
- i += len;
- }
- if (space)
- *space = '\0';
- }
- return (string);
- }
- /*****************************************************************************
- * Function: void _DtHelpCeCompressSpace (string)
- *
- * Parameters: string to process
- *
- * Return Value: processed string
- *
- * Purpose: This function strips all leading and trailing spaces
- * from the string; it also compresses any intervening
- * spaces into a single space. This is useful when
- * comparing name strings. For instance, the string:
- * " First Middle Last "
- *
- * would compress to:
- *
- * "First Middle Last"
- *
- * Processing is in place.
- *
- *****************************************************************************/
- void _DtHelpCeCompressSpace (
- char * string)
- {
- char * ptr;
- /* Strip leading and trailing spaces */
- _DtHelpCeStripSpaces(string);
- /* Compress intervening spaces */
- _DtHelpCeStrchr(string, " ", 1, &ptr);
- while (ptr)
- {
- /* Skip over the one space we plan to keep */
- ptr++;
- _DtHelpCeStripSpaces(ptr);
- _DtHelpCeStrchr(ptr, " ", 1, &ptr);
- }
- }
- /*****************************************************************************
- * Function: void _DtHelpCeIconvStr1Step (string)
- *
- * Parameters:
- * fromCode; codeset name
- * fromStr; string to convert
- * toCode; codeset name
- * ret_toStr; converted str; this string is malloc'd by this routine
- * and the CALLER MUST FREE it when no longer needed.
- * dflt1; 1-byte default char
- * dflt2; 2-byte default char
- *
- * Return Value:
- * 0: ok
- * -1: missing (NULL) argument
- * -2: no translation available from fromCode to toCode
- * -3: couldn't allocate memory
- * -4: couldn't start conversion
- * -5: incomplete multibyte char
- * -6: invalid char found
- *
- * Purpose:
- * Converts string from fromCode to toCode using iconv(3)
- * It expects the codeset strings to be iconv(3) compatible.
- *
- * Comments:
- * iconv(3) is standardized in XPG4, which is just starting
- * to be supported. Below are several different implementations
- * of _DtHelpCeIconvStr, each using what is available on different
- * platforms. If no code is #ifdef'd, the XPG4 code defaults.
- *****************************************************************************/
- int _DtHelpCeIconvStr1Step(
- const char * fromCode, /* codeset name */
- const char * fromStr, /* string to convert */
- const char * toCode, /* codeset name */
- char * * ret_toStr, /* converted str */
- int dflt1, /* 1-byte default char */
- int dflt2) /* 2-byte default char */
- {
- _DtHelpCeIconvContextRec * iconvContext;
- int ret;
- ret = _DtHelpCeIconvOpen(&iconvContext,fromCode,toCode,dflt1,dflt2);
- if (0 == ret)
- ret = _DtHelpCeIconvStr(iconvContext,fromStr, ret_toStr,NULL,NULL,0);
- _DtHelpCeIconvClose(&iconvContext);
- return ret;
- }
- /*****************************************************************************
- * Function: void _DtHelpCeIconvOpen (string)
- *
- * Parameters:
- * iconvContext context
- * fromStr; string to convert
- * ret_toStr; converted str; this string is malloc'd by this routine
- * and the CALLER MUST FREE it when no longer needed.
- * dflt1; 1-byte default char
- * dflt2; 2-byte default char
- *
- * Return Value:
- * 0: ok
- * -1: missing (NULL) argument
- * -2: no translation available from fromCode to toCode
- * -3: couldn't allocate memory
- * -4: couldn't start conversion
- * -5: incomplete multibyte char
- * -6: invalid char found
- *
- * Purpose:
- * Opens an iconv table/algorithm to convert string from
- * fromCode to toCode using iconv(3)
- * It expects the codeset strings to be iconv(3) compatible.
- *
- * Comments:
- * iconv(3) is standardized in XPG4, which is just starting
- * to be supported. Below are several different implementations
- * of _DtHelpCeIconvStr, each using what is available on different
- * platforms. If no code is #ifdef'd, the XPG4 code defaults.
- *****************************************************************************/
- int _DtHelpCeIconvOpen(
- _DtHelpCeIconvContext * ret_iconvContext, /* iconv */
- const char * fromCode, /* codeset name */
- const char * toCode, /* codeset name */
- int dflt1, /* 1-byte default char */
- int dflt2) /* 2-byte default char */
- { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
- int err; /* error code of function */
- _DtHelpCeIconvContextRec * ic;
- #define BAD (-1)
- #define MEM_INC 20
- err = 0; /* ok */
- /* check args */
- if (!ret_iconvContext || !fromCode || !toCode )
- return -1; /* RETURN error */
- /* init state */
- ic = *ret_iconvContext = calloc(1,sizeof(_DtHelpCeIconvContextRec));
- if (NULL == ic) return -3; /* RETURN error */
- if ( strcmp(fromCode,toCode) == 0 )
- {
- ic->cd = (iconv_t) BAD; /* BAD means use strdup() */
- goto success;
- }
- ic->cd = iconv_open(toCode,fromCode);
- if ( ic->cd == (iconv_t) BAD )
- {
- err = -4; /* error */
- goto success;
- }
- success:
- ic->fromCodeset = strdup(fromCode);
- ic->toCodeset = strdup(toCode);
- return err; /* RETURN status */
- }
- /*****************************************************************************
- * Function: void _DtHelpCeIconvStr (string)
- *
- * Parameters:
- * iconvContext context for the conversion
- * fromStr; string to convert
- * ret_toStr; converted str; this string is malloc'd by this routine
- * and the CALLER MUST FREE it when no longer needed.
- * toStrBuf; for efficiency, can pass in a buf
- * toStrBufLen; length of buf
- *
- * Return Value:
- * 0: ok
- * -1: missing (NULL) argument
- * -2: no translation available from fromCode to toCode
- * -3: couldn't allocate memory
- * -4: couldn't start conversion
- * -5: incomplete multibyte char
- * -6: invalid char found
- *
- * Purpose:
- * Converts string from fromCode to toCode using iconv(3)
- * If toStrBuf is NULL, memory for the converted string
- * will be malloced as needed.
- * If toStrBuf is not NULL, the conversion will use up
- * to toStrBufLen bytes of the buffer and then realloc
- * more memory if needed.
- * If toStrBuf is not NULL, the size of the buf is
- * returned in ret_toStrLen; otherwise, the value is
- * not set.
- * ret_toStr receives the pointer to the buf, which may
- * be different from toStrBuf if memory was allocated
- * or NULL if an error occurred. If toStrBuf is
- * not NULL and memory must be allocated, a realloc()
- * call is used, possibly invalidating the toStrBuf ptr.
- * ret_toStrLen receives the length of the buffer if
- * toStrBuf is not NULL. If it is NULL, the length
- * is not returned.
- * Comments:
- * iconv(3) is standardized in XPG4, which is just starting
- * to be supported. Below are several different implementations
- * of _DtHelpCeIconvStr, each using what is available on different
- * platforms. If no code is #ifdef'd, the XPG4 code defaults.
- *****************************************************************************/
- int _DtHelpCeIconvStr(
- _DtHelpCeIconvContext iconvContext, /* iconv */
- const char * fromStr, /* string to convert */
- char * * ret_toStr, /* converted str */
- size_t * ret_toStrLen, /* converted str */
- char * toStrBuf, /* for efficiency, can pass in a buf */
- size_t toStrBufLen) /* length of buf */
- { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
- char * toStr; /* ptr to tostr memory */
- int toStrSize; /* size of mallocd string */
- size_t inBytesLeft; /* bytes left to use from input buf */
- const char * inChar; /* ptr into fromstr */
- char * outChar; /* ptr into tostr */
- size_t outBytesLeft; /* bytes left in the output str */
- int err; /* error code of function */
- #define BAD (-1)
- #define MEM_INC 20
- /* init ret values; allows function to be called nicely in a loop. */
- if (ret_toStr) *ret_toStr = toStrBuf;
- if (ret_toStrLen) *ret_toStrLen = toStrBufLen;
- /* check args */
- if ( !iconvContext || !fromStr || !ret_toStr
- || (!ret_toStrLen && toStrBuf))
- return -1; /* RETURN error */
- /* just do a straight copy if codesets the same or invalid context */
- if ( iconvContext->cd == (iconv_t) BAD )
- {
- if (NULL == toStrBuf)
- {
- *ret_toStr = strdup(fromStr);
- }
- else /* reuse the buffer */
- {
- int len = strlen(fromStr) + 1;
- if (len > toStrBufLen)
- *ret_toStr = realloc(toStrBuf,len);
- else
- {
- *ret_toStr = toStrBuf;
- len = toStrBufLen;
- }
- /* set return values */
- strcpy(*ret_toStr,fromStr);
- *ret_toStrLen = len;
- }
- return (NULL != *ret_toStr ? 0 : -3); /* RETURN result */
- }
- /* init ptrs */
- toStr = toStrBuf;
- toStrSize = (NULL == toStrBuf ? 0 : toStrBufLen);
- inChar = fromStr;
- inBytesLeft = strlen(fromStr);
- outChar = toStr;
- outBytesLeft = toStrSize;
- /* translate the string */
- err = -3;
- while ( inBytesLeft > 0 )
- {
- /* convert a character */
- if(iconv(iconvContext->cd, (ICONV_INBUF_TYPE)&inChar,
- &inBytesLeft,&outChar,&outBytesLeft) == -1)
- {
- switch(errno)
- {
- case 0: /* no error */
- continue;
- case EINVAL: /* inChar pts to incomplete multibyte char */
- inBytesLeft = 0; /* end the translation */
- err = -5;
- break;
- case EILSEQ: /* invalid char at inChar */
- inBytesLeft = 0; /* end the translation */
- err = -6;
- break;
- case E2BIG: /* no room in toStr */
- /* provide enough mem in the toStr */
- if (outBytesLeft < sizeof(wchar_t))
- {
- size_t offset = outChar - (char *) toStr;
-
- outBytesLeft += MEM_INC;
- toStrSize += MEM_INC;
- toStr = realloc(toStr,toStrSize * sizeof(char));
- if (NULL == toStr)
- {
- inBytesLeft = 0; /* end the translation */
- err = -3;
- break; /* BREAK */
- }
- outChar = (char *) (toStr + offset); /* recalc ptr */
- }
- break;
- default:
- inBytesLeft = 0; /* breakout of loop */
- break;
- } /* switch on convertsion result */
- } /* if an error */
- } /* while chars left to translate */
- /* set the EOS */
- if(outChar) *outChar = EOS;
- /* set return values */
- *ret_toStr = (char *) toStr;
- if (toStrBuf) *ret_toStrLen = toStrSize;
- return (NULL != toStr ? 0 : err); /* RETURN result */
- }
- /*****************************************************************************
- * Function: void _DtHelpCeIconvClose()
- *
- * Parameters:
- * io_iconvContext; context
- *
- * Return Value: none
- *
- * Purpose:
- * Closes an iconv context used to convert
- * fromCode to toCode using iconv(3)
- *
- * Comments:
- * iconv(3) is standardized in XPG4, which is just starting
- * to be supported. Below are several different implementations
- * of _DtHelpCeIconvStr, each using what is available on different
- * platforms. If no code is #ifdef'd, the XPG4 code defaults.
- *****************************************************************************/
- void _DtHelpCeIconvClose(
- _DtHelpCeIconvContext * io_iconvContext)
- { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
- _DtHelpCeIconvContextRec * ic;
- if (!io_iconvContext || NULL == *io_iconvContext) return;
- ic = *io_iconvContext;
- if ( ic->cd != (iconv_t) BAD )
- iconv_close(ic->cd);
- if (ic->fromCodeset) free(ic->fromCodeset);
- if (ic->toCodeset) free(ic->toCodeset);
- free(ic);
- *io_iconvContext = NULL;
- }
- /*****************************************************************************
- * Function: void _DtHelpCeIconvContextSuitable()
- *
- * Parameters:
- * iconvContext: context
- * fromCode: proposed fromCodeset
- * toCode: proposed toCodeset
- *
- * Return Value: True: proposed conversion compatible with this context
- * False: proposed conversion is not compatible
- *
- * Purpose:
- * Checks whether the proposed conversion from
- * fromCodeset to toCodeset can be handled by
- * the iconv context that already exists.
- *
- * Comments:
- * This function is designed to allow a context
- * to stay open as long as possible and avoid
- * closing and then reopening the contexts for
- * the same conversion.
- *****************************************************************************/
- int _DtHelpCeIconvContextSuitable(
- _DtHelpCeIconvContext iconvContext,
- const char * fromCode,
- const char * toCode)
- {
- if ( !iconvContext
- || !iconvContext->fromCodeset
- || !iconvContext->toCodeset
- || !fromCode
- || !toCode)
- return False;
- if ( strcmp(iconvContext->fromCodeset,fromCode) == 0
- && strcmp(iconvContext->toCodeset,toCode) == 0)
- return True;
- return False;
- }
- #if defined(_AIX)
- /*****************************************************************************
- * Function: _DtHelpCeStrCaseCmp
- *
- * Parameters:
- *
- * Return Value:
- *
- * Purpose: IBM does not support the 'strcasecmp' routine. This takes it's
- * place.
- *****************************************************************************/
- int
- _DtHelpCeStrCaseCmp (
- const char *s1,
- const char *s2)
- {
- return (_DtCvStrCaseCmp(s1, s2));
- }
- #endif /* _AIX */
- /******************************************************************************
- * Function: int _DtHelpCeFreeStringArray (char **array)
- *
- * Parameters: array A pointer to the NULL-terminated
- * string array which is to be freed.
- *
- * Return Value: 0 if successful, -1 if a failure occurs
- *
- * Purpose: Free the memory used for a NULL-terminated string array.
- *
- ******************************************************************************/
- int
- _DtHelpCeFreeStringArray (char **array)
- {
- char **next;
- if (array == NULL)
- return -1;
- for (next = array; *next != NULL; next++)
- free (*next);
- free (array);
- return (0);
- }
- /****************************************************************************
- * Function: void **_DtHelpCeAddPtrToArray (void **array, void *ptr)
- *
- * Parameters: array A pointer to a NULL-terminated array
- * of pointers.
- * ptr The pointer which is to be added to
- * the end of the array.
- *
- * Returns: A pointer to the NULL-terminated array created
- * by adding 'ptr' to the end of 'array'.
- *
- * Purpose: Add a new element to a NULL-terminated array of pointers.
- * These are typed as "void *" so that they can be used with
- * pointers to any type of data.
- *
- ****************************************************************************/
- void **
- _DtHelpCeAddPtrToArray (
- void **array,
- void *ptr)
- {
- return (_DtCvAddPtrToArray(array, ptr));
- }
- /*****************************************************************************
- * Function: _DtHelpCeStrCaseCmpLatin1
- *
- * Parameters:
- *
- * Return Value:
- *
- * Purpose: Use a version of CaseCmp that does not go through tolower().
- * This routine should be used only for compares that now the
- * strings are in English (iso8859-1) and do not want setlocale
- * to screw it up.
- *****************************************************************************/
- int
- _DtHelpCeStrCaseCmpLatin1 (
- const char *s1,
- const char *s2)
- {
- return (_DtCvStrCaseCmpLatin1(s1, s2));
- }
- /*****************************************************************************
- * Function: _DtHelpCeStrNCaseCmpLatin1
- *
- * Parameters:
- *
- * Return Value:
- *
- * Purpose: Use a version of CaseCmp that does not go through tolower().
- * This routine should be used only for compares that now the
- * strings are in English (iso8859-1) and do not want setlocale
- * to screw it up.
- *****************************************************************************/
- int
- _DtHelpCeStrNCaseCmpLatin1 (
- const char *s1,
- const char *s2,
- size_t n)
- {
- return (_DtCvStrNCaseCmpLatin1(s1, s2, n));
- }
|