]>
git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/sortkey.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1996-2012, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
9 //===============================================================================
15 // Created by: Helena Shih
17 // Modification History:
19 // Date Name Description
21 // 6/20/97 helena Java class name change.
22 // 6/23/97 helena Added comments to make code more readable.
23 // 6/26/98 erm Canged to use byte arrays instead of UnicodeString
24 // 7/31/98 erm hashCode: minimum inc should be 2 not 1,
25 // Cleaned up operator=
26 // 07/12/99 helena HPUX 11 CC port.
27 // 03/06/01 synwee Modified compareTo, to handle the result of
28 // 2 string similar in contents, but one is longer
30 //===============================================================================
32 #include "unicode/utypes.h"
34 #if !UCONFIG_NO_COLLATION
36 #include "unicode/sortkey.h"
43 // A hash code of kInvalidHashCode indicates that the hash code needs
44 // to be computed. A hash code of kEmptyHashCode is used for empty keys
45 // and for any key whose computed hash code is kInvalidHashCode.
46 static const int32_t kInvalidHashCode
= 0;
47 static const int32_t kEmptyHashCode
= 1;
48 // The "bogus hash code" replaces a separate fBogus flag.
49 static const int32_t kBogusHashCode
= 2;
51 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationKey
)
53 CollationKey::CollationKey()
54 : UObject(), fFlagAndLength(0),
55 fHashCode(kEmptyHashCode
)
59 // Create a collation key from a bit array.
60 CollationKey::CollationKey(const uint8_t* newValues
, int32_t count
)
61 : UObject(), fFlagAndLength(count
),
62 fHashCode(kInvalidHashCode
)
64 if (count
< 0 || (newValues
== NULL
&& count
!= 0) ||
65 (count
> getCapacity() && reallocate(count
, 0) == NULL
)) {
71 uprv_memcpy(getBytes(), newValues
, count
);
75 CollationKey::CollationKey(const CollationKey
& other
)
76 : UObject(other
), fFlagAndLength(other
.getLength()),
77 fHashCode(other
.fHashCode
)
85 int32_t length
= fFlagAndLength
;
86 if (length
> getCapacity() && reallocate(length
, 0) == NULL
) {
92 uprv_memcpy(getBytes(), other
.getBytes(), length
);
96 CollationKey::~CollationKey()
98 if(fFlagAndLength
< 0) { uprv_free(fUnion
.fFields
.fBytes
); }
101 uint8_t *CollationKey::reallocate(int32_t newCapacity
, int32_t length
) {
102 uint8_t *newBytes
= static_cast<uint8_t *>(uprv_malloc(newCapacity
));
103 if(newBytes
== NULL
) { return NULL
; }
105 uprv_memcpy(newBytes
, getBytes(), length
);
107 if(fFlagAndLength
< 0) { uprv_free(fUnion
.fFields
.fBytes
); }
108 fUnion
.fFields
.fBytes
= newBytes
;
109 fUnion
.fFields
.fCapacity
= newCapacity
;
110 fFlagAndLength
|= 0x80000000;
114 void CollationKey::setLength(int32_t newLength
) {
115 // U_ASSERT(newLength >= 0 && newLength <= getCapacity());
116 fFlagAndLength
= (fFlagAndLength
& 0x80000000) | newLength
;
117 fHashCode
= kInvalidHashCode
;
120 // set the key to an empty state
122 CollationKey::reset()
124 fFlagAndLength
&= 0x80000000;
125 fHashCode
= kEmptyHashCode
;
130 // set the key to a "bogus" or invalid state
132 CollationKey::setToBogus()
134 fFlagAndLength
&= 0x80000000;
135 fHashCode
= kBogusHashCode
;
141 CollationKey::operator==(const CollationKey
& source
) const
143 return getLength() == source
.getLength() &&
145 uprv_memcmp(getBytes(), source
.getBytes(), getLength()) == 0);
149 CollationKey::operator=(const CollationKey
& other
)
158 int32_t length
= other
.getLength();
159 if (length
> getCapacity() && reallocate(length
, 0) == NULL
) {
163 uprv_memcpy(getBytes(), other
.getBytes(), length
);
165 fFlagAndLength
= (fFlagAndLength
& 0x80000000) | length
;
166 fHashCode
= other
.fHashCode
;
172 // Bitwise comparison for the collation keys.
173 Collator::EComparisonResult
174 CollationKey::compareTo(const CollationKey
& target
) const
176 UErrorCode errorCode
= U_ZERO_ERROR
;
177 return static_cast<Collator::EComparisonResult
>(compareTo(target
, errorCode
));
180 // Bitwise comparison for the collation keys.
182 CollationKey::compareTo(const CollationKey
& target
, UErrorCode
&status
) const
184 if(U_SUCCESS(status
)) {
185 const uint8_t *src
= getBytes();
186 const uint8_t *tgt
= target
.getBytes();
188 // are we comparing the same string
192 UCollationResult result
;
194 // are we comparing different lengths?
195 int32_t minLength
= getLength();
196 int32_t targetLength
= target
.getLength();
197 if (minLength
< targetLength
) {
199 } else if (minLength
== targetLength
) {
202 minLength
= targetLength
;
203 result
= UCOL_GREATER
;
207 int diff
= uprv_memcmp(src
, tgt
, minLength
);
223 #ifdef U_USE_COLLATION_KEY_DEPRECATES
224 // Create a copy of the byte array.
226 CollationKey::toByteArray(int32_t& count
) const
228 uint8_t *result
= (uint8_t*) uprv_malloc( sizeof(uint8_t) * fCount
);
238 uprv_memcpy(result
, fBytes
, fCount
);
247 computeHashCode(const uint8_t *key
, int32_t length
) {
248 const char *s
= reinterpret_cast<const char *>(key
);
250 if (s
== NULL
|| length
== 0) {
251 hash
= kEmptyHashCode
;
253 hash
= ustr_hashCharsN(s
, length
);
254 if (hash
== kInvalidHashCode
|| hash
== kBogusHashCode
) {
255 hash
= kEmptyHashCode
;
262 CollationKey::hashCode() const
264 // (Cribbed from UnicodeString)
265 // We cache the hashCode; when it becomes invalid, due to any change to the
266 // string, we note this by setting it to kInvalidHashCode. [LIU]
268 // Note: This method is semantically const, but physically non-const.
270 if (fHashCode
== kInvalidHashCode
)
272 fHashCode
= computeHashCode(getBytes(), getLength());
280 U_CAPI
int32_t U_EXPORT2
281 ucol_keyHashCode(const uint8_t *key
,
284 return icu::computeHashCode(key
, length
);
287 #endif /* #if !UCONFIG_NO_COLLATION */