1999-08-16 21:50:52 +00:00
|
|
|
/*
|
|
|
|
*******************************************************************************
|
2000-01-13 23:54:23 +00:00
|
|
|
*
|
|
|
|
* Copyright (C) 1998-1999, International Business Machines
|
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
*
|
1999-08-16 21:50:52 +00:00
|
|
|
*******************************************************************************
|
|
|
|
*
|
|
|
|
* File ustring.h
|
|
|
|
*
|
|
|
|
* Modification History:
|
|
|
|
*
|
|
|
|
* Date Name Description
|
|
|
|
* 12/07/98 bertrand Creation.
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
1999-12-28 23:39:02 +00:00
|
|
|
#include "unicode/ustring.h"
|
|
|
|
#include "unicode/utypes.h"
|
1999-08-16 21:50:52 +00:00
|
|
|
#include "cstring.h"
|
1999-12-09 01:03:31 +00:00
|
|
|
#include "umutex.h"
|
1999-12-28 23:39:02 +00:00
|
|
|
#include "unicode/ucnv.h"
|
1999-08-16 21:50:52 +00:00
|
|
|
|
1999-12-09 01:03:31 +00:00
|
|
|
/* forward declaractions of definitions for the shared default converter */
|
1999-08-16 21:50:52 +00:00
|
|
|
|
1999-12-09 01:03:31 +00:00
|
|
|
static UConverter *fgDefaultConverter = NULL;
|
1999-08-16 21:50:52 +00:00
|
|
|
|
1999-12-09 01:03:31 +00:00
|
|
|
static UConverter*
|
2000-03-24 17:45:45 +00:00
|
|
|
getDefaultConverter(void);
|
1999-12-09 01:03:31 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
releaseDefaultConverter(UConverter *converter);
|
1999-08-16 21:50:52 +00:00
|
|
|
|
1999-12-09 01:03:31 +00:00
|
|
|
/* ANSI string.h - style functions ------------------------------------------ */
|
|
|
|
|
|
|
|
#define MAX_STRLEN 0x0FFFFFFF
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
UChar*
|
|
|
|
u_strcat(UChar *dst,
|
|
|
|
const UChar *src)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
UChar *anchor = dst; /* save a pointer to start of dst */
|
|
|
|
|
|
|
|
while(*dst != 0) { /* To end of first string */
|
|
|
|
++dst;
|
|
|
|
}
|
|
|
|
while((*dst = *src) != 0) { /* copy string 2 over */
|
|
|
|
++dst;
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
|
1999-08-16 21:50:52 +00:00
|
|
|
return anchor;
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar*
|
|
|
|
u_strncat(UChar *dst,
|
|
|
|
const UChar *src,
|
|
|
|
int32_t n )
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
if(n > 0) {
|
|
|
|
UChar *anchor = dst; /* save a pointer to start of dst */
|
|
|
|
|
|
|
|
while(*dst != 0) { /* To end of first string */
|
|
|
|
++dst;
|
|
|
|
}
|
|
|
|
while((*dst = *src) != 0) { /* copy string 2 over */
|
|
|
|
++dst;
|
|
|
|
if(--n == 0) {
|
|
|
|
*dst = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++src;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
|
1999-12-08 00:15:46 +00:00
|
|
|
return anchor;
|
|
|
|
} else {
|
|
|
|
return dst;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UChar*
|
|
|
|
u_strchr(const UChar *s,
|
|
|
|
UChar c)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
while(*s != 0) {
|
|
|
|
if(*s == c) {
|
|
|
|
return (UChar *)s;
|
|
|
|
}
|
|
|
|
++s;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-06-29 18:52:11 +00:00
|
|
|
U_CAPI UChar * U_EXPORT2
|
|
|
|
u_strstr(const UChar *s, const UChar *substring) {
|
|
|
|
if(*substring == 0) {
|
|
|
|
return (UChar *)s;
|
|
|
|
} else if(substring[1] == 0) {
|
|
|
|
return u_strchr(s, *substring);
|
|
|
|
} else {
|
|
|
|
/* ### TBD */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-06-29 19:00:55 +00:00
|
|
|
U_CAPI UChar * U_EXPORT2
|
|
|
|
u_strchr32(const UChar *s, UChar32 c) {
|
|
|
|
if(!UTF_NEED_MULTIPLE_UCHAR(c)) {
|
|
|
|
return u_strchr(s, (UChar)c);
|
|
|
|
} else {
|
|
|
|
UChar buffer[UTF_MAX_CHAR_LENGTH + 1];
|
|
|
|
UTextOffset i = 0;
|
|
|
|
UTF_APPEND_CHAR_UNSAFE(buffer, i, c);
|
|
|
|
buffer[i] = 0;
|
|
|
|
return u_strstr(s, buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-16 21:50:52 +00:00
|
|
|
int32_t
|
|
|
|
u_strcmp(const UChar *s1,
|
|
|
|
const UChar *s2)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
int32_t rc;
|
|
|
|
for(;;) {
|
|
|
|
rc = (int32_t)*s1 - (int32_t)*s2;
|
|
|
|
if(rc != 0 || *s1 == 0) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
++s1;
|
|
|
|
++s2;
|
1999-08-16 21:50:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
u_strncmp(const UChar *s1,
|
|
|
|
const UChar *s2,
|
|
|
|
int32_t n)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
if(n > 0) {
|
|
|
|
int32_t rc;
|
|
|
|
for(;;) {
|
|
|
|
rc = (int32_t)*s1 - (int32_t)*s2;
|
|
|
|
if(rc != 0 || *s1 == 0 || --n == 0) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
++s1;
|
|
|
|
++s2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
1999-08-16 21:50:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar*
|
|
|
|
u_strcpy(UChar *dst,
|
|
|
|
const UChar *src)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
UChar *anchor = dst; /* save a pointer to start of dst */
|
|
|
|
|
|
|
|
while((*dst = *src) != 0) { /* copy string 2 over */
|
|
|
|
++dst;
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
|
1999-08-16 21:50:52 +00:00
|
|
|
return anchor;
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar*
|
|
|
|
u_strncpy(UChar *dst,
|
|
|
|
const UChar *src,
|
|
|
|
int32_t n)
|
|
|
|
{
|
1999-12-08 00:15:46 +00:00
|
|
|
UChar *anchor = dst; /* save a pointer to start of dst */
|
|
|
|
|
|
|
|
if(n > 0) {
|
|
|
|
while((*dst = *src) != 0) { /* copy string 2 over */
|
|
|
|
++dst;
|
|
|
|
if(--n == 0) {
|
|
|
|
*dst = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*dst = 0;
|
|
|
|
}
|
|
|
|
|
1999-08-16 21:50:52 +00:00
|
|
|
return anchor;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
u_strlen(const UChar *s)
|
|
|
|
{
|
2000-04-06 23:06:48 +00:00
|
|
|
# if U_SIZEOF_WCHAR_T == U_SIZEOF_UCHAR
|
|
|
|
return uprv_wcslen(s);
|
|
|
|
# else
|
1999-12-08 00:15:46 +00:00
|
|
|
const UChar *t = s;
|
|
|
|
while(*t != 0) {
|
|
|
|
++t;
|
|
|
|
}
|
|
|
|
return t - s;
|
2000-04-06 23:06:48 +00:00
|
|
|
#endif
|
1999-08-16 21:50:52 +00:00
|
|
|
}
|
|
|
|
|
1999-12-09 01:03:31 +00:00
|
|
|
/* conversions between char* and UChar* ------------------------------------- */
|
1999-08-16 21:50:52 +00:00
|
|
|
|
|
|
|
UChar* u_uastrcpy(UChar *ucs1,
|
|
|
|
const char *s2 )
|
|
|
|
{
|
1999-12-09 01:03:31 +00:00
|
|
|
UConverter *cnv = getDefaultConverter();
|
|
|
|
if(cnv != NULL) {
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
ucnv_toUChars(cnv,
|
|
|
|
ucs1,
|
|
|
|
MAX_STRLEN,
|
|
|
|
s2,
|
1999-12-28 23:39:02 +00:00
|
|
|
uprv_strlen(s2),
|
1999-12-09 01:03:31 +00:00
|
|
|
&err);
|
|
|
|
releaseDefaultConverter(cnv);
|
|
|
|
if(U_FAILURE(err)) {
|
|
|
|
*ucs1 = 0;
|
|
|
|
}
|
|
|
|
} else {
|
1999-12-08 00:15:46 +00:00
|
|
|
*ucs1 = 0;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
return ucs1;
|
|
|
|
}
|
|
|
|
|
|
|
|
UChar* u_uastrncpy(UChar *ucs1,
|
|
|
|
const char *s2 ,
|
|
|
|
int32_t n)
|
|
|
|
{
|
2000-06-29 01:41:04 +00:00
|
|
|
UChar *target = ucs1;
|
1999-12-09 01:03:31 +00:00
|
|
|
UConverter *cnv = getDefaultConverter();
|
|
|
|
if(cnv != NULL) {
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2000-06-29 01:41:04 +00:00
|
|
|
ucnv_reset(cnv);
|
|
|
|
ucnv_toUnicode(cnv,
|
|
|
|
&target,
|
|
|
|
ucs1+n,
|
|
|
|
&s2,
|
|
|
|
s2+uprv_strlen(s2),
|
|
|
|
NULL,
|
|
|
|
TRUE,
|
|
|
|
&err);
|
|
|
|
ucnv_reset(cnv); /* be good citizens */
|
1999-12-09 01:03:31 +00:00
|
|
|
releaseDefaultConverter(cnv);
|
2000-06-29 01:41:04 +00:00
|
|
|
if(U_FAILURE(err) && (err != U_INDEX_OUTOFBOUNDS_ERROR) ) {
|
|
|
|
*ucs1 = 0; /* failure */
|
|
|
|
}
|
|
|
|
if(target < (ucs1+n)) { /* Indexoutofbounds isn't an err, just means no termination will happen. */
|
|
|
|
*target = 0; /* terminate */
|
1999-12-09 01:03:31 +00:00
|
|
|
}
|
|
|
|
} else {
|
1999-12-08 00:15:46 +00:00
|
|
|
*ucs1 = 0;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
return ucs1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* u_austrcpy(char *s1,
|
|
|
|
const UChar *ucs2 )
|
|
|
|
{
|
1999-12-09 01:03:31 +00:00
|
|
|
UConverter *cnv = getDefaultConverter();
|
|
|
|
if(cnv != NULL) {
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
int32_t len = ucnv_fromUChars(cnv,
|
|
|
|
s1,
|
|
|
|
MAX_STRLEN,
|
|
|
|
ucs2,
|
2000-03-07 01:42:40 +00:00
|
|
|
-1,
|
1999-12-09 01:03:31 +00:00
|
|
|
&err);
|
|
|
|
releaseDefaultConverter(cnv);
|
|
|
|
s1[len] = 0;
|
|
|
|
} else {
|
|
|
|
*s1 = 0;
|
|
|
|
}
|
1999-08-16 21:50:52 +00:00
|
|
|
return s1;
|
|
|
|
}
|
1999-12-09 01:03:31 +00:00
|
|
|
|
|
|
|
/* mutexed access to a shared default converter ----------------------------- */
|
|
|
|
|
|
|
|
/* this is the same implementation as in unistr.cpp */
|
|
|
|
|
|
|
|
static UConverter*
|
|
|
|
getDefaultConverter()
|
|
|
|
{
|
|
|
|
UConverter *converter = NULL;
|
|
|
|
|
|
|
|
if(fgDefaultConverter != NULL) {
|
|
|
|
umtx_lock(NULL);
|
|
|
|
|
|
|
|
/* need to check to make sure it wasn't taken out from under us */
|
|
|
|
if(fgDefaultConverter != NULL) {
|
|
|
|
converter = fgDefaultConverter;
|
|
|
|
fgDefaultConverter = NULL;
|
|
|
|
}
|
|
|
|
umtx_unlock(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if the cache was empty, create a converter */
|
|
|
|
if(converter == NULL) {
|
|
|
|
UErrorCode status = U_ZERO_ERROR;
|
|
|
|
converter = ucnv_open(NULL, &status);
|
|
|
|
if(U_FAILURE(status)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return converter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
releaseDefaultConverter(UConverter *converter)
|
|
|
|
{
|
|
|
|
if(fgDefaultConverter == NULL) {
|
|
|
|
umtx_lock(NULL);
|
|
|
|
|
|
|
|
if(fgDefaultConverter == NULL) {
|
|
|
|
fgDefaultConverter = converter;
|
|
|
|
converter = NULL;
|
|
|
|
}
|
|
|
|
umtx_unlock(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(converter != NULL) {
|
|
|
|
ucnv_close(converter);
|
|
|
|
}
|
|
|
|
}
|
2000-06-29 19:36:20 +00:00
|
|
|
|
|
|
|
U_CAPI int32_t U_EXPORT2
|
|
|
|
u_unescapeChars(const char *s,
|
|
|
|
UChar *dest, int32_t destSize) {
|
|
|
|
/* ### TBD */
|
|
|
|
return 0;
|
|
|
|
}
|