/* ******************************************************************************* * * Copyright (C) 2001, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: ustrcase.c * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 2002feb20 * created by: Markus W. Scherer * * Implementation file for string casing C API functions. * Uses functions from uchar.c for basic functionality that requires access * to the Unicode Character Database (uprops.dat). */ #include "unicode/utypes.h" #include "unicode/ustring.h" #include "unicode/ubrk.h" #include "cmemory.h" #include "unormimp.h" #include "ustr_imp.h" /* string casing ------------------------------------------------------------ */ #if !UCONFIG_NO_BREAK_ITERATION /* * Internal titlecasing function, * using u_internalStrToLower() and u_internalToTitle(). * * Must get titleIter!=NULL. */ U_CFUNC int32_t u_internalStrToTitle(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, UBreakIterator *titleIter, const char *locale, UErrorCode *pErrorCode) { UCharIterator iter; UChar32 c; int32_t prev, index, destIndex, length; UBool isFirstIndex; /* set up local variables */ uiter_setString(&iter, src, srcLength); destIndex=0; prev=0; isFirstIndex=TRUE; /* titlecasing loop */ while(prevsrcLength) { index=srcLength; } /* lowercase [prev..index[ */ if(prev=srcLength) { break; } /* titlecase the character at the found index */ UTF_NEXT_CHAR(src, index, srcLength, c); iter.move(&iter, index, UITER_ZERO); if(destIndex0) || src==NULL || srcLength<-1 ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the string length */ if(srcLength==-1) { srcLength=u_strlen(src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { /* overlap: provide a temporary destination buffer and later copy the result */ if(destCapacity<=(sizeof(buffer)/U_SIZEOF_UCHAR)) { /* the stack buffer is large enough */ temp=buffer; } else { /* allocate a buffer */ temp=(UChar *)uprv_malloc(destCapacity*U_SIZEOF_UCHAR); if(temp==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return 0; } } } else { temp=dest; } ownTitleIter=FALSE; destLength=0; if(toWhichCase==TO_LOWER) { destLength=u_internalStrToLower(temp, destCapacity, src, srcLength, 0, srcLength, locale, pErrorCode); } else if(toWhichCase==TO_UPPER) { destLength=u_internalStrToUpper(temp, destCapacity, src, srcLength, locale, pErrorCode); #if !UCONFIG_NO_BREAK_ITERATION } else if(toWhichCase==TO_TITLE) { if(titleIter==NULL) { titleIter=ubrk_open(UBRK_WORD, locale, src, srcLength, pErrorCode); ownTitleIter=(UBool)U_SUCCESS(*pErrorCode); } if(U_SUCCESS(*pErrorCode)) { destLength=u_internalStrToTitle(temp, destCapacity, src, srcLength, titleIter, locale, pErrorCode); } #endif } else { destLength=u_internalStrFoldCase(temp, destCapacity, src, srcLength, options, pErrorCode); } if(temp!=dest) { /* copy the result string to the destination buffer */ if(destLength>0) { int32_t copyLength= destLength<=destCapacity ? destLength : destCapacity; if(copyLength>0) { uprv_memmove(dest, temp, copyLength*U_SIZEOF_UCHAR); } } if(temp!=buffer) { uprv_free(temp); } } #if !UCONFIG_NO_BREAK_ITERATION if(ownTitleIter) { ubrk_close(titleIter); } #endif return u_terminateUChars(dest, destCapacity, destLength, pErrorCode); } U_CAPI int32_t U_EXPORT2 u_strToLower(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode) { return u_strCaseMap(dest, destCapacity, src, srcLength, NULL, locale, 0, TO_LOWER, pErrorCode); } U_CAPI int32_t U_EXPORT2 u_strToUpper(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode) { return u_strCaseMap(dest, destCapacity, src, srcLength, NULL, locale, 0, TO_UPPER, pErrorCode); } U_CAPI int32_t U_EXPORT2 u_strToTitle(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, UBreakIterator *titleIter, const char *locale, UErrorCode *pErrorCode) { return u_strCaseMap(dest, destCapacity, src, srcLength, titleIter, locale, 0, TO_TITLE, pErrorCode); } U_CAPI int32_t U_EXPORT2 u_strFoldCase(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, uint32_t options, UErrorCode *pErrorCode) { return u_strCaseMap(dest, destCapacity, src, srcLength, NULL, NULL, options, FOLD_CASE, pErrorCode); } /* case-insensitive string comparisons */ U_CAPI int32_t U_EXPORT2 u_strCaseCompare(const UChar *s1, int32_t length1, const UChar *s2, int32_t length2, uint32_t options, UErrorCode *pErrorCode) { /* argument checking */ if(pErrorCode==0 || U_FAILURE(*pErrorCode)) { return 0; } if(s1==NULL || length1<-1 || s2==NULL || length2<-1) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } return unorm_cmpEquivFold(s1, length1, s2, length2, options|U_COMPARE_IGNORE_CASE, pErrorCode); } U_CAPI int32_t U_EXPORT2 u_strcasecmp(const UChar *s1, const UChar *s2, uint32_t options) { UErrorCode errorCode=U_ZERO_ERROR; return unorm_cmpEquivFold(s1, -1, s2, -1, options|U_COMPARE_IGNORE_CASE, &errorCode); } U_CAPI int32_t U_EXPORT2 u_memcasecmp(const UChar *s1, const UChar *s2, int32_t length, uint32_t options) { UErrorCode errorCode=U_ZERO_ERROR; return unorm_cmpEquivFold(s1, length, s2, length, options|U_COMPARE_IGNORE_CASE, &errorCode); } U_CAPI int32_t U_EXPORT2 u_strncasecmp(const UChar *s1, const UChar *s2, int32_t n, uint32_t options) { UErrorCode errorCode=U_ZERO_ERROR; return unorm_cmpEquivFold(s1, n, s2, n, options|(U_COMPARE_IGNORE_CASE|_STRNCMP_STYLE), &errorCode); }