intl/icu/source/common/unistr_case.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2 *******************************************************************************
     3 *
     4 *   Copyright (C) 1999-2011, International Business Machines
     5 *   Corporation and others.  All Rights Reserved.
     6 *
     7 *******************************************************************************
     8 *   file name:  unistr_case.cpp
     9 *   encoding:   US-ASCII
    10 *   tab size:   8 (not used)
    11 *   indentation:2
    12 *
    13 *   created on: 2004aug19
    14 *   created by: Markus W. Scherer
    15 *
    16 *   Case-mapping functions moved here from unistr.cpp
    17 */
    19 #include "unicode/utypes.h"
    20 #include "unicode/putil.h"
    21 #include "cstring.h"
    22 #include "cmemory.h"
    23 #include "unicode/ustring.h"
    24 #include "unicode/unistr.h"
    25 #include "unicode/uchar.h"
    26 #include "uelement.h"
    27 #include "ustr_imp.h"
    29 U_NAMESPACE_BEGIN
    31 //========================================
    32 // Read-only implementation
    33 //========================================
    35 int8_t
    36 UnicodeString::doCaseCompare(int32_t start,
    37                              int32_t length,
    38                              const UChar *srcChars,
    39                              int32_t srcStart,
    40                              int32_t srcLength,
    41                              uint32_t options) const
    42 {
    43   // compare illegal string values
    44   // treat const UChar *srcChars==NULL as an empty string
    45   if(isBogus()) {
    46     return -1;
    47   }
    49   // pin indices to legal values
    50   pinIndices(start, length);
    52   if(srcChars == NULL) {
    53     srcStart = srcLength = 0;
    54   }
    56   // get the correct pointer
    57   const UChar *chars = getArrayStart();
    59   chars += start;
    60   if(srcStart!=0) {
    61     srcChars += srcStart;
    62   }
    64   if(chars != srcChars) {
    65     UErrorCode errorCode=U_ZERO_ERROR;
    66     int32_t result=u_strcmpFold(chars, length, srcChars, srcLength,
    67                                 options|U_COMPARE_IGNORE_CASE, &errorCode);
    68     if(result!=0) {
    69       return (int8_t)(result >> 24 | 1);
    70     }
    71   } else {
    72     // get the srcLength if necessary
    73     if(srcLength < 0) {
    74       srcLength = u_strlen(srcChars + srcStart);
    75     }
    76     if(length != srcLength) {
    77       return (int8_t)((length - srcLength) >> 24 | 1);
    78     }
    79   }
    80   return 0;
    81 }
    83 //========================================
    84 // Write implementation
    85 //========================================
    87 UnicodeString &
    88 UnicodeString::caseMap(const UCaseMap *csm,
    89                        UStringCaseMapper *stringCaseMapper) {
    90   if(isEmpty() || !isWritable()) {
    91     // nothing to do
    92     return *this;
    93   }
    95   // We need to allocate a new buffer for the internal string case mapping function.
    96   // This is very similar to how doReplace() keeps the old array pointer
    97   // and deletes the old array itself after it is done.
    98   // In addition, we are forcing cloneArrayIfNeeded() to always allocate a new array.
    99   UChar oldStackBuffer[US_STACKBUF_SIZE];
   100   UChar *oldArray;
   101   int32_t oldLength;
   103   if(fFlags&kUsingStackBuffer) {
   104     // copy the stack buffer contents because it will be overwritten
   105     u_memcpy(oldStackBuffer, fUnion.fStackBuffer, fShortLength);
   106     oldArray = oldStackBuffer;
   107     oldLength = fShortLength;
   108   } else {
   109     oldArray = getArrayStart();
   110     oldLength = length();
   111   }
   113   int32_t capacity;
   114   if(oldLength <= US_STACKBUF_SIZE) {
   115     capacity = US_STACKBUF_SIZE;
   116   } else {
   117     capacity = oldLength + 20;
   118   }
   119   int32_t *bufferToDelete = 0;
   120   if(!cloneArrayIfNeeded(capacity, capacity, FALSE, &bufferToDelete, TRUE)) {
   121     return *this;
   122   }
   124   // Case-map, and if the result is too long, then reallocate and repeat.
   125   UErrorCode errorCode;
   126   int32_t newLength;
   127   do {
   128     errorCode = U_ZERO_ERROR;
   129     newLength = stringCaseMapper(csm, getArrayStart(), getCapacity(),
   130                                  oldArray, oldLength, &errorCode);
   131     setLength(newLength);
   132   } while(errorCode==U_BUFFER_OVERFLOW_ERROR && cloneArrayIfNeeded(newLength, newLength, FALSE));
   134   if (bufferToDelete) {
   135     uprv_free(bufferToDelete);
   136   }
   137   if(U_FAILURE(errorCode)) {
   138     setToBogus();
   139   }
   140   return *this;
   141 }
   143 UnicodeString &
   144 UnicodeString::foldCase(uint32_t options) {
   145   UCaseMap csm=UCASEMAP_INITIALIZER;
   146   csm.csp=ucase_getSingleton();
   147   csm.options=options;
   148   return caseMap(&csm, ustrcase_internalFold);
   149 }
   151 U_NAMESPACE_END
   153 // Defined here to reduce dependencies on break iterator
   154 U_CAPI int32_t U_EXPORT2
   155 uhash_hashCaselessUnicodeString(const UElement key) {
   156     U_NAMESPACE_USE
   157     const UnicodeString *str = (const UnicodeString*) key.pointer;
   158     if (str == NULL) {
   159         return 0;
   160     }
   161     // Inefficient; a better way would be to have a hash function in
   162     // UnicodeString that does case folding on the fly.
   163     UnicodeString copy(*str);
   164     return copy.foldCase().hashCode();
   165 }
   167 // Defined here to reduce dependencies on break iterator
   168 U_CAPI UBool U_EXPORT2
   169 uhash_compareCaselessUnicodeString(const UElement key1, const UElement key2) {
   170     U_NAMESPACE_USE
   171     const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
   172     const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
   173     if (str1 == str2) {
   174         return TRUE;
   175     }
   176     if (str1 == NULL || str2 == NULL) {
   177         return FALSE;
   178     }
   179     return str1->caseCompare(*str2, U_FOLD_CASE_DEFAULT) == 0;
   180 }

mercurial