OLD | NEW |
1 /* | 1 /* |
2 ********************************************************************** | 2 ********************************************************************** |
3 * Copyright (C) 2001-2008 IBM and others. All rights reserved. | 3 * Copyright (C) 2001-2014 IBM and others. All rights reserved. |
4 ********************************************************************** | 4 ********************************************************************** |
5 * Date Name Description | 5 * Date Name Description |
6 * 03/22/2000 helena Creation. | 6 * 03/22/2000 helena Creation. |
7 ********************************************************************** | 7 ********************************************************************** |
8 */ | 8 */ |
9 | 9 |
10 #include "unicode/utypes.h" | 10 #include "unicode/utypes.h" |
11 | 11 |
12 #if !UCONFIG_NO_COLLATION && !UCONFIG_NO_BREAK_ITERATION | 12 #if !UCONFIG_NO_COLLATION && !UCONFIG_NO_BREAK_ITERATION |
13 | 13 |
14 #include "unicode/stsearch.h" | 14 #include "unicode/stsearch.h" |
15 #include "usrchimp.h" | 15 #include "usrchimp.h" |
16 #include "cmemory.h" | 16 #include "cmemory.h" |
17 | 17 |
18 U_NAMESPACE_BEGIN | 18 U_NAMESPACE_BEGIN |
19 | 19 |
20 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringSearch) | 20 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringSearch) |
21 | 21 |
22 // public constructors and destructors ----------------------------------- | 22 // public constructors and destructors ----------------------------------- |
23 | 23 |
24 StringSearch::StringSearch(const UnicodeString &pattern, | 24 StringSearch::StringSearch(const UnicodeString &pattern, |
25 const UnicodeString &text, | 25 const UnicodeString &text, |
26 const Locale &locale, | 26 const Locale &locale, |
27 BreakIterator *breakiter, | 27 BreakIterator *breakiter, |
28 UErrorCode &status) : | 28 UErrorCode &status) : |
29 SearchIterator(text, breakiter), | 29 SearchIterator(text, breakiter), |
30 m_collator_(), | |
31 m_pattern_(pattern) | 30 m_pattern_(pattern) |
32 { | 31 { |
33 if (U_FAILURE(status)) { | 32 if (U_FAILURE(status)) { |
34 m_strsrch_ = NULL; | 33 m_strsrch_ = NULL; |
35 return; | 34 return; |
36 } | 35 } |
37 | 36 |
38 m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(), | 37 m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(), |
39 m_text_.getBuffer(), m_text_.length(), | 38 m_text_.getBuffer(), m_text_.length(), |
40 locale.getName(), (UBreakIterator *)breakiter, | 39 locale.getName(), (UBreakIterator *)breakiter, |
41 &status); | 40 &status); |
42 uprv_free(m_search_); | 41 uprv_free(m_search_); |
43 m_search_ = NULL; | 42 m_search_ = NULL; |
44 | 43 |
45 // !!! dlf m_collator_ is an odd beast. basically it is an aliasing | |
46 // wrapper around the internal collator and rules, which (here) are | |
47 // owned by this stringsearch object. this means 1) it's destructor | |
48 // _should not_ delete the ucollator or rules, and 2) changes made | |
49 // to the exposed collator (setStrength etc) _should_ modify the | |
50 // ucollator. thus the collator is not a copy-on-write alias, and it | |
51 // needs to distinguish itself not merely from 'stand alone' colators | |
52 // but also from copy-on-write ones. it needs additional state, which | |
53 // setUCollator should set. | |
54 | |
55 if (U_SUCCESS(status)) { | 44 if (U_SUCCESS(status)) { |
56 // Alias the collator | |
57 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
58 // m_search_ has been created by the base SearchIterator class | 45 // m_search_ has been created by the base SearchIterator class |
59 m_search_ = m_strsrch_->search; | 46 m_search_ = m_strsrch_->search; |
60 } | 47 } |
61 } | 48 } |
62 | 49 |
63 StringSearch::StringSearch(const UnicodeString &pattern, | 50 StringSearch::StringSearch(const UnicodeString &pattern, |
64 const UnicodeString &text, | 51 const UnicodeString &text, |
65 RuleBasedCollator *coll, | 52 RuleBasedCollator *coll, |
66 BreakIterator *breakiter, | 53 BreakIterator *breakiter, |
67 UErrorCode &status) : | 54 UErrorCode &status) : |
68 SearchIterator(text, breakiter), | 55 SearchIterator(text, breakiter), |
69 m_collator_(), | |
70 m_pattern_(pattern) | 56 m_pattern_(pattern) |
71 { | 57 { |
72 if (U_FAILURE(status)) { | 58 if (U_FAILURE(status)) { |
73 m_strsrch_ = NULL; | 59 m_strsrch_ = NULL; |
74 return; | 60 return; |
75 } | 61 } |
76 if (coll == NULL) { | 62 if (coll == NULL) { |
77 status = U_ILLEGAL_ARGUMENT_ERROR; | 63 status = U_ILLEGAL_ARGUMENT_ERROR; |
78 m_strsrch_ = NULL; | 64 m_strsrch_ = NULL; |
79 return; | 65 return; |
80 } | 66 } |
81 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), | 67 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), |
82 m_pattern_.length(), | 68 m_pattern_.length(), |
83 m_text_.getBuffer(), | 69 m_text_.getBuffer(), |
84 m_text_.length(), coll->ucollator, | 70 m_text_.length(), coll->toUCollator(), |
85 (UBreakIterator *)breakiter, | 71 (UBreakIterator *)breakiter, |
86 &status); | 72 &status); |
87 uprv_free(m_search_); | 73 uprv_free(m_search_); |
88 m_search_ = NULL; | 74 m_search_ = NULL; |
89 | 75 |
90 if (U_SUCCESS(status)) { | 76 if (U_SUCCESS(status)) { |
91 // Alias the collator | |
92 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
93 // m_search_ has been created by the base SearchIterator class | 77 // m_search_ has been created by the base SearchIterator class |
94 m_search_ = m_strsrch_->search; | 78 m_search_ = m_strsrch_->search; |
95 } | 79 } |
96 } | 80 } |
97 | 81 |
98 StringSearch::StringSearch(const UnicodeString &pattern, | 82 StringSearch::StringSearch(const UnicodeString &pattern, |
99 CharacterIterator &text, | 83 CharacterIterator &text, |
100 const Locale &locale, | 84 const Locale &locale, |
101 BreakIterator *breakiter, | 85 BreakIterator *breakiter, |
102 UErrorCode &status) : | 86 UErrorCode &status) : |
103 SearchIterator(text, breakiter), | 87 SearchIterator(text, breakiter), |
104 m_collator_(), | |
105 m_pattern_(pattern) | 88 m_pattern_(pattern) |
106 { | 89 { |
107 if (U_FAILURE(status)) { | 90 if (U_FAILURE(status)) { |
108 m_strsrch_ = NULL; | 91 m_strsrch_ = NULL; |
109 return; | 92 return; |
110 } | 93 } |
111 m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(), | 94 m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(), |
112 m_text_.getBuffer(), m_text_.length(), | 95 m_text_.getBuffer(), m_text_.length(), |
113 locale.getName(), (UBreakIterator *)breakiter, | 96 locale.getName(), (UBreakIterator *)breakiter, |
114 &status); | 97 &status); |
115 uprv_free(m_search_); | 98 uprv_free(m_search_); |
116 m_search_ = NULL; | 99 m_search_ = NULL; |
117 | 100 |
118 if (U_SUCCESS(status)) { | 101 if (U_SUCCESS(status)) { |
119 // Alias the collator | |
120 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
121 // m_search_ has been created by the base SearchIterator class | 102 // m_search_ has been created by the base SearchIterator class |
122 m_search_ = m_strsrch_->search; | 103 m_search_ = m_strsrch_->search; |
123 } | 104 } |
124 } | 105 } |
125 | 106 |
126 StringSearch::StringSearch(const UnicodeString &pattern, | 107 StringSearch::StringSearch(const UnicodeString &pattern, |
127 CharacterIterator &text, | 108 CharacterIterator &text, |
128 RuleBasedCollator *coll, | 109 RuleBasedCollator *coll, |
129 BreakIterator *breakiter, | 110 BreakIterator *breakiter, |
130 UErrorCode &status) : | 111 UErrorCode &status) : |
131 SearchIterator(text, breakiter), | 112 SearchIterator(text, breakiter), |
132 m_collator_(), | |
133 m_pattern_(pattern) | 113 m_pattern_(pattern) |
134 { | 114 { |
135 if (U_FAILURE(status)) { | 115 if (U_FAILURE(status)) { |
136 m_strsrch_ = NULL; | 116 m_strsrch_ = NULL; |
137 return; | 117 return; |
138 } | 118 } |
139 if (coll == NULL) { | 119 if (coll == NULL) { |
140 status = U_ILLEGAL_ARGUMENT_ERROR; | 120 status = U_ILLEGAL_ARGUMENT_ERROR; |
141 m_strsrch_ = NULL; | 121 m_strsrch_ = NULL; |
142 return; | 122 return; |
143 } | 123 } |
144 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), | 124 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), |
145 m_pattern_.length(), | 125 m_pattern_.length(), |
146 m_text_.getBuffer(), | 126 m_text_.getBuffer(), |
147 m_text_.length(), coll->ucollator, | 127 m_text_.length(), coll->toUCollator(), |
148 (UBreakIterator *)breakiter, | 128 (UBreakIterator *)breakiter, |
149 &status); | 129 &status); |
150 uprv_free(m_search_); | 130 uprv_free(m_search_); |
151 m_search_ = NULL; | 131 m_search_ = NULL; |
152 | 132 |
153 if (U_SUCCESS(status)) { | 133 if (U_SUCCESS(status)) { |
154 // Alias the collator | |
155 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
156 // m_search_ has been created by the base SearchIterator class | 134 // m_search_ has been created by the base SearchIterator class |
157 m_search_ = m_strsrch_->search; | 135 m_search_ = m_strsrch_->search; |
158 } | 136 } |
159 } | 137 } |
160 | 138 |
161 StringSearch::StringSearch(const StringSearch &that) : | 139 StringSearch::StringSearch(const StringSearch &that) : |
162 SearchIterator(that.m_text_, that.m_breakiterator_), | 140 SearchIterator(that.m_text_, that.m_breakiterator_), |
163 m_collator_(), | |
164 m_pattern_(that.m_pattern_) | 141 m_pattern_(that.m_pattern_) |
165 { | 142 { |
166 UErrorCode status = U_ZERO_ERROR; | 143 UErrorCode status = U_ZERO_ERROR; |
167 | 144 |
168 // Free m_search_ from the superclass | 145 // Free m_search_ from the superclass |
169 uprv_free(m_search_); | 146 uprv_free(m_search_); |
170 m_search_ = NULL; | 147 m_search_ = NULL; |
171 | 148 |
172 if (that.m_strsrch_ == NULL) { | 149 if (that.m_strsrch_ == NULL) { |
173 // This was not a good copy | 150 // This was not a good copy |
174 m_strsrch_ = NULL; | 151 m_strsrch_ = NULL; |
175 } | 152 } |
176 else { | 153 else { |
177 // Make a deep copy | 154 // Make a deep copy |
178 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), | 155 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), |
179 m_pattern_.length(), | 156 m_pattern_.length(), |
180 m_text_.getBuffer(), | 157 m_text_.getBuffer(), |
181 m_text_.length(), | 158 m_text_.length(), |
182 that.m_strsrch_->collator, | 159 that.m_strsrch_->collator, |
183 (UBreakIterator *)that.m_breakitera
tor_, | 160 (UBreakIterator *)that.m_breakitera
tor_, |
184 &status); | 161 &status); |
185 if (U_SUCCESS(status)) { | 162 if (U_SUCCESS(status)) { |
186 // Alias the collator | |
187 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
188 // m_search_ has been created by the base SearchIterator class | 163 // m_search_ has been created by the base SearchIterator class |
189 m_search_ = m_strsrch_->search; | 164 m_search_ = m_strsrch_->search; |
190 } | 165 } |
191 } | 166 } |
192 } | 167 } |
193 | 168 |
194 StringSearch::~StringSearch() | 169 StringSearch::~StringSearch() |
195 { | 170 { |
196 if (m_strsrch_ != NULL) { | 171 if (m_strsrch_ != NULL) { |
197 usearch_close(m_strsrch_); | 172 usearch_close(m_strsrch_); |
(...skipping 17 matching lines...) Expand all Loading... |
215 // all m_search_ in the parent class is linked up with m_strsrch_ | 190 // all m_search_ in the parent class is linked up with m_strsrch_ |
216 usearch_close(m_strsrch_); | 191 usearch_close(m_strsrch_); |
217 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), | 192 m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(), |
218 m_pattern_.length(), | 193 m_pattern_.length(), |
219 m_text_.getBuffer(), | 194 m_text_.getBuffer(), |
220 m_text_.length(), | 195 m_text_.length(), |
221 that.m_strsrch_->collator, | 196 that.m_strsrch_->collator, |
222 NULL, &status); | 197 NULL, &status); |
223 // Check null pointer | 198 // Check null pointer |
224 if (m_strsrch_ != NULL) { | 199 if (m_strsrch_ != NULL) { |
225 » // Alias the collator | 200 m_search_ = m_strsrch_->search; |
226 » m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
227 » m_search_ = m_strsrch_->search; | |
228 } | 201 } |
229 } | 202 } |
230 return *this; | 203 return *this; |
231 } | 204 } |
232 | 205 |
233 UBool StringSearch::operator==(const SearchIterator &that) const | 206 UBool StringSearch::operator==(const SearchIterator &that) const |
234 { | 207 { |
235 if (this == &that) { | 208 if (this == &that) { |
236 return TRUE; | 209 return TRUE; |
237 } | 210 } |
(...skipping 29 matching lines...) Expand all Loading... |
267 void StringSearch::setText(CharacterIterator &text, UErrorCode &status) | 240 void StringSearch::setText(CharacterIterator &text, UErrorCode &status) |
268 { | 241 { |
269 if (U_SUCCESS(status)) { | 242 if (U_SUCCESS(status)) { |
270 text.getText(m_text_); | 243 text.getText(m_text_); |
271 usearch_setText(m_strsrch_, m_text_.getBuffer(), m_text_.length(), &stat
us); | 244 usearch_setText(m_strsrch_, m_text_.getBuffer(), m_text_.length(), &stat
us); |
272 } | 245 } |
273 } | 246 } |
274 | 247 |
275 RuleBasedCollator * StringSearch::getCollator() const | 248 RuleBasedCollator * StringSearch::getCollator() const |
276 { | 249 { |
277 return (RuleBasedCollator *)&m_collator_; | 250 // Note the const_cast. It would be cleaner if this const method returned a
const collator. |
| 251 return RuleBasedCollator::rbcFromUCollator(const_cast<UCollator *>(m_strsrch
_->collator)); |
278 } | 252 } |
279 | 253 |
280 void StringSearch::setCollator(RuleBasedCollator *coll, UErrorCode &status) | 254 void StringSearch::setCollator(RuleBasedCollator *coll, UErrorCode &status) |
281 { | 255 { |
282 if (U_SUCCESS(status)) { | 256 if (U_SUCCESS(status)) { |
283 usearch_setCollator(m_strsrch_, coll->getUCollator(), &status); | 257 usearch_setCollator(m_strsrch_, coll->toUCollator(), &status); |
284 // Alias the collator | |
285 m_collator_.setUCollator((UCollator *)m_strsrch_->collator); | |
286 } | 258 } |
287 } | 259 } |
288 | 260 |
289 void StringSearch::setPattern(const UnicodeString &pattern, | 261 void StringSearch::setPattern(const UnicodeString &pattern, |
290 UErrorCode &status) | 262 UErrorCode &status) |
291 { | 263 { |
292 if (U_SUCCESS(status)) { | 264 if (U_SUCCESS(status)) { |
293 m_pattern_ = pattern; | 265 m_pattern_ = pattern; |
294 usearch_setPattern(m_strsrch_, m_pattern_.getBuffer(), m_pattern_.length
(), | 266 usearch_setPattern(m_strsrch_, m_pattern_.getBuffer(), m_pattern_.length
(), |
295 &status); | 267 &status); |
296 } | 268 } |
297 } | 269 } |
298 | 270 |
299 const UnicodeString & StringSearch::getPattern() const | 271 const UnicodeString & StringSearch::getPattern() const |
300 { | 272 { |
301 return m_pattern_; | 273 return m_pattern_; |
302 } | 274 } |
303 | 275 |
304 // public methods ---------------------------------------------------- | 276 // public methods ---------------------------------------------------- |
305 | 277 |
306 void StringSearch::reset() | 278 void StringSearch::reset() |
307 { | 279 { |
308 usearch_reset(m_strsrch_); | 280 usearch_reset(m_strsrch_); |
309 } | 281 } |
310 | 282 |
311 SearchIterator * StringSearch::safeClone(void) const | 283 SearchIterator * StringSearch::safeClone(void) const |
312 { | 284 { |
313 UErrorCode status = U_ZERO_ERROR; | 285 UErrorCode status = U_ZERO_ERROR; |
314 StringSearch *result = new StringSearch(m_pattern_, m_text_, | 286 StringSearch *result = new StringSearch(m_pattern_, m_text_, |
315 (RuleBasedCollator *)&m_collator_, | 287 getCollator(), |
316 m_breakiterator_, | 288 m_breakiterator_, |
317 status); | 289 status); |
318 /* test for NULL */ | 290 /* test for NULL */ |
319 if (result == 0) { | 291 if (result == 0) { |
320 status = U_MEMORY_ALLOCATION_ERROR; | 292 status = U_MEMORY_ALLOCATION_ERROR; |
321 return 0; | 293 return 0; |
322 } | 294 } |
323 result->setOffset(getOffset(), status); | 295 result->setOffset(getOffset(), status); |
324 result->setMatchStart(m_strsrch_->search->matchedIndex); | 296 result->setMatchStart(m_strsrch_->search->matchedIndex); |
325 result->setMatchLength(m_strsrch_->search->matchedLength); | 297 result->setMatchLength(m_strsrch_->search->matchedLength); |
326 if (U_FAILURE(status)) { | 298 if (U_FAILURE(status)) { |
327 return NULL; | 299 return NULL; |
328 } | 300 } |
329 return result; | 301 return result; |
330 } | 302 } |
331 | 303 |
332 // protected method ------------------------------------------------- | 304 // protected method ------------------------------------------------- |
333 | 305 |
334 int32_t StringSearch::handleNext(int32_t position, UErrorCode &status) | 306 int32_t StringSearch::handleNext(int32_t position, UErrorCode &status) |
335 { | 307 { |
336 // values passed here are already in the pre-shift position | 308 // values passed here are already in the pre-shift position |
337 if (U_SUCCESS(status)) { | 309 if (U_SUCCESS(status)) { |
338 if (m_strsrch_->pattern.CELength == 0) { | 310 if (m_strsrch_->pattern.cesLength == 0) { |
339 m_search_->matchedIndex = | 311 m_search_->matchedIndex = |
340 m_search_->matchedIndex == USEARCH_DONE ? | 312 m_search_->matchedIndex == USEARCH_DONE ? |
341 getOffset() : m_search_->matchedIndex + 1; | 313 getOffset() : m_search_->matchedIndex + 1; |
342 m_search_->matchedLength = 0; | 314 m_search_->matchedLength = 0; |
343 ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, | 315 ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, |
344 &status); | 316 &status); |
345 if (m_search_->matchedIndex == m_search_->textLength) { | 317 if (m_search_->matchedIndex == m_search_->textLength) { |
346 m_search_->matchedIndex = USEARCH_DONE; | 318 m_search_->matchedIndex = USEARCH_DONE; |
347 } | 319 } |
348 } | 320 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 #endif | 398 #endif |
427 } | 399 } |
428 } | 400 } |
429 return USEARCH_DONE; | 401 return USEARCH_DONE; |
430 } | 402 } |
431 | 403 |
432 int32_t StringSearch::handlePrev(int32_t position, UErrorCode &status) | 404 int32_t StringSearch::handlePrev(int32_t position, UErrorCode &status) |
433 { | 405 { |
434 // values passed here are already in the pre-shift position | 406 // values passed here are already in the pre-shift position |
435 if (U_SUCCESS(status)) { | 407 if (U_SUCCESS(status)) { |
436 if (m_strsrch_->pattern.CELength == 0) { | 408 if (m_strsrch_->pattern.cesLength == 0) { |
437 m_search_->matchedIndex = | 409 m_search_->matchedIndex = |
438 (m_search_->matchedIndex == USEARCH_DONE ? getOffset() : | 410 (m_search_->matchedIndex == USEARCH_DONE ? getOffset() : |
439 m_search_->matchedIndex); | 411 m_search_->matchedIndex); |
440 if (m_search_->matchedIndex == 0) { | 412 if (m_search_->matchedIndex == 0) { |
441 setMatchNotFound(); | 413 setMatchNotFound(); |
442 } | 414 } |
443 else { | 415 else { |
444 m_search_->matchedIndex --; | 416 m_search_->matchedIndex --; |
445 ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, | 417 ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, |
446 &status); | 418 &status); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 } | 472 } |
501 | 473 |
502 return m_search_->matchedIndex; | 474 return m_search_->matchedIndex; |
503 } | 475 } |
504 return USEARCH_DONE; | 476 return USEARCH_DONE; |
505 } | 477 } |
506 | 478 |
507 U_NAMESPACE_END | 479 U_NAMESPACE_END |
508 | 480 |
509 #endif /* #if !UCONFIG_NO_COLLATION */ | 481 #endif /* #if !UCONFIG_NO_COLLATION */ |
OLD | NEW |