2 **********************************************************************
3 * Copyright (C) 2001 IBM and others. All rights reserved.
4 **********************************************************************
5 * Date Name Description
6 * 03/22/2000 helena Creation.
7 **********************************************************************
10 #include "unicode/utypes.h"
12 #if !UCONFIG_NO_COLLATION
14 #include "unicode/brkiter.h"
15 #include "unicode/schriter.h"
16 #include "unicode/search.h"
20 // public constructors and destructors -----------------------------------
23 SearchIterator::SearchIterator(const SearchIterator
&other
)
26 m_breakiterator_
= other
.m_breakiterator_
;
27 m_text_
= other
.m_text_
;
28 m_search_
= (USearch
*)uprv_malloc(sizeof(USearch
));
29 m_search_
->breakIter
= other
.m_search_
->breakIter
;
30 m_search_
->isCanonicalMatch
= other
.m_search_
->isCanonicalMatch
;
31 m_search_
->isOverlap
= other
.m_search_
->isOverlap
;
32 m_search_
->matchedIndex
= other
.m_search_
->matchedIndex
;
33 m_search_
->matchedLength
= other
.m_search_
->matchedLength
;
34 m_search_
->text
= other
.m_search_
->text
;
35 m_search_
->textLength
= other
.m_search_
->textLength
;
38 SearchIterator::~SearchIterator()
40 if (m_search_
!= NULL
) {
45 // public get and set methods ----------------------------------------
47 void SearchIterator::setAttribute(USearchAttribute attribute
,
48 USearchAttributeValue value
,
51 if (U_SUCCESS(status
)) {
54 case USEARCH_OVERLAP
:
55 m_search_
->isOverlap
= (value
== USEARCH_ON
? TRUE
: FALSE
);
57 case USEARCH_CANONICAL_MATCH
:
58 m_search_
->isCanonicalMatch
= (value
== USEARCH_ON
? TRUE
: FALSE
);
61 status
= U_ILLEGAL_ARGUMENT_ERROR
;
64 if (value
== USEARCH_ATTRIBUTE_VALUE_COUNT
) {
65 status
= U_ILLEGAL_ARGUMENT_ERROR
;
69 USearchAttributeValue
SearchIterator::getAttribute(
70 USearchAttribute attribute
) const
73 case USEARCH_OVERLAP
:
74 return (m_search_
->isOverlap
== TRUE
? USEARCH_ON
: USEARCH_OFF
);
75 case USEARCH_CANONICAL_MATCH
:
76 return (m_search_
->isCanonicalMatch
== TRUE
? USEARCH_ON
:
79 return USEARCH_DEFAULT
;
83 int32_t SearchIterator::getMatchedStart() const
85 return m_search_
->matchedIndex
;
88 int32_t SearchIterator::getMatchedLength() const
90 return m_search_
->matchedLength
;
93 void SearchIterator::getMatchedText(UnicodeString
&result
) const
95 int32_t matchedindex
= m_search_
->matchedIndex
;
96 int32_t matchedlength
= m_search_
->matchedLength
;
97 if (matchedindex
!= USEARCH_DONE
&& matchedlength
!= 0) {
98 result
.setTo(m_search_
->text
+ matchedindex
, matchedlength
);
105 void SearchIterator::setBreakIterator(BreakIterator
*breakiter
,
108 if (U_SUCCESS(status
)) {
109 m_search_
->breakIter
= NULL
;
110 // the c++ breakiterator may not make use of ubreakiterator.
111 // so we'll have to keep track of it ourselves.
112 m_breakiterator_
= breakiter
;
116 const BreakIterator
* SearchIterator::getBreakIterator(void) const
118 return m_breakiterator_
;
121 void SearchIterator::setText(const UnicodeString
&text
, UErrorCode
&status
)
123 if (U_SUCCESS(status
)) {
124 if (text
.length() == 0) {
125 status
= U_ILLEGAL_ARGUMENT_ERROR
;
129 m_search_
->text
= m_text_
.getBuffer();
130 m_search_
->textLength
= m_text_
.length();
135 void SearchIterator::setText(CharacterIterator
&text
, UErrorCode
&status
)
137 if (U_SUCCESS(status
)) {
138 text
.getText(m_text_
);
139 setText(m_text_
, status
);
143 const UnicodeString
& SearchIterator::getText(void) const
148 // operator overloading ----------------------------------------------
150 UBool
SearchIterator::operator==(const SearchIterator
&that
) const
155 return (m_breakiterator_
== that
.m_breakiterator_
&&
156 m_search_
->isCanonicalMatch
== that
.m_search_
->isCanonicalMatch
&&
157 m_search_
->isOverlap
== that
.m_search_
->isOverlap
&&
158 m_search_
->matchedIndex
== that
.m_search_
->matchedIndex
&&
159 m_search_
->matchedLength
== that
.m_search_
->matchedLength
&&
160 m_search_
->textLength
== that
.m_search_
->textLength
&&
161 getOffset() == that
.getOffset() &&
162 (uprv_memcmp(m_search_
->text
, that
.m_search_
->text
,
163 m_search_
->textLength
* sizeof(UChar
)) == 0));
166 // public methods ----------------------------------------------------
168 int32_t SearchIterator::first(UErrorCode
&status
)
170 if (U_FAILURE(status
)) {
173 setOffset(0, status
);
174 return handleNext(0, status
);
177 int32_t SearchIterator::following(int32_t position
,
180 if (U_FAILURE(status
)) {
183 setOffset(position
, status
);
184 return handleNext(position
, status
);
187 int32_t SearchIterator::last(UErrorCode
&status
)
189 if (U_FAILURE(status
)) {
192 setOffset(m_search_
->textLength
, status
);
193 return handlePrev(m_search_
->textLength
, status
);
196 int32_t SearchIterator::preceding(int32_t position
,
199 if (U_FAILURE(status
)) {
202 setOffset(position
, status
);
203 return handlePrev(position
, status
);
206 int32_t SearchIterator::next(UErrorCode
&status
)
208 if (U_SUCCESS(status
)) {
209 int32_t offset
= getOffset();
210 int32_t matchindex
= m_search_
->matchedIndex
;
211 int32_t matchlength
= m_search_
->matchedLength
;
212 m_search_
->reset
= FALSE
;
213 if (m_search_
->isForwardSearching
== TRUE
) {
214 int32_t textlength
= m_search_
->textLength
;
215 if (offset
== textlength
|| matchindex
== textlength
||
216 (matchindex
!= USEARCH_DONE
&&
217 matchindex
+ matchlength
>= textlength
)) {
218 // not enough characters to match
224 // switching direction.
225 // if matchedIndex == USEARCH_DONE, it means that either a
226 // setOffset has been called or that previous ran off the text
227 // string. the iterator would have been set to offset 0 if a
228 // match is not found.
229 m_search_
->isForwardSearching
= TRUE
;
230 if (m_search_
->matchedIndex
!= USEARCH_DONE
) {
231 // there's no need to set the collation element iterator
232 // the next call to next will set the offset.
237 if (matchlength
> 0) {
238 // if matchlength is 0 we are at the start of the iteration
239 if (m_search_
->isOverlap
) {
243 offset
+= matchlength
;
246 return handleNext(offset
, status
);
251 int32_t SearchIterator::previous(UErrorCode
&status
)
253 if (U_SUCCESS(status
)) {
255 if (m_search_
->reset
) {
256 offset
= m_search_
->textLength
;
257 m_search_
->isForwardSearching
= FALSE
;
258 m_search_
->reset
= FALSE
;
259 setOffset(offset
, status
);
262 offset
= getOffset();
265 int32_t matchindex
= m_search_
->matchedIndex
;
266 if (m_search_
->isForwardSearching
== TRUE
) {
267 // switching direction.
268 // if matchedIndex == USEARCH_DONE, it means that either a
269 // setOffset has been called or that next ran off the text
270 // string. the iterator would have been set to offset textLength if
271 // a match is not found.
272 m_search_
->isForwardSearching
= FALSE
;
273 if (matchindex
!= USEARCH_DONE
) {
278 if (offset
== 0 || matchindex
== 0) {
279 // not enough characters to match
285 if (matchindex
!= USEARCH_DONE
) {
286 return handlePrev(matchindex
, status
);
288 return handlePrev(offset
, status
);
293 void SearchIterator::reset()
295 UErrorCode status
= U_ZERO_ERROR
;
297 setOffset(0, status
);
298 m_search_
->isOverlap
= FALSE
;
299 m_search_
->isCanonicalMatch
= FALSE
;
300 m_search_
->isForwardSearching
= TRUE
;
301 m_search_
->reset
= TRUE
;
304 // protected constructors and destructors -----------------------------
306 SearchIterator::SearchIterator()
308 m_search_
= (USearch
*)uprv_malloc(sizeof(USearch
));
309 m_search_
->breakIter
= NULL
;
310 m_search_
->isOverlap
= FALSE
;
311 m_search_
->isCanonicalMatch
= FALSE
;
312 m_search_
->isForwardSearching
= TRUE
;
313 m_search_
->reset
= TRUE
;
314 m_search_
->matchedIndex
= USEARCH_DONE
;
315 m_search_
->matchedLength
= 0;
316 m_search_
->text
= NULL
;
317 m_search_
->textLength
= 0;
320 SearchIterator::SearchIterator(const UnicodeString
&text
,
321 BreakIterator
*breakiter
) :
322 m_breakiterator_(breakiter
),
325 m_search_
= (USearch
*)uprv_malloc(sizeof(USearch
));
326 m_search_
->breakIter
= NULL
;
327 m_search_
->isOverlap
= FALSE
;
328 m_search_
->isCanonicalMatch
= FALSE
;
329 m_search_
->isForwardSearching
= TRUE
;
330 m_search_
->reset
= TRUE
;
331 m_search_
->matchedIndex
= USEARCH_DONE
;
332 m_search_
->matchedLength
= 0;
333 m_search_
->text
= m_text_
.getBuffer();
334 m_search_
->textLength
= text
.length();
337 SearchIterator::SearchIterator(CharacterIterator
&text
,
338 BreakIterator
*breakiter
) :
339 m_breakiterator_(breakiter
)
341 m_search_
= (USearch
*)uprv_malloc(sizeof(USearch
));
342 m_search_
->breakIter
= NULL
;
343 m_search_
->isOverlap
= FALSE
;
344 m_search_
->isCanonicalMatch
= FALSE
;
345 m_search_
->isForwardSearching
= TRUE
;
346 m_search_
->reset
= TRUE
;
347 m_search_
->matchedIndex
= USEARCH_DONE
;
348 m_search_
->matchedLength
= 0;
349 text
.getText(m_text_
);
350 m_search_
->text
= m_text_
.getBuffer();
351 m_search_
->textLength
= m_text_
.length();
352 m_breakiterator_
= breakiter
;
355 // protected methods ------------------------------------------------------
357 SearchIterator
& SearchIterator::operator=(const SearchIterator
&that
)
360 m_breakiterator_
= that
.m_breakiterator_
;
361 m_text_
= that
.m_text_
;
362 m_search_
->breakIter
= that
.m_search_
->breakIter
;
363 m_search_
->isCanonicalMatch
= that
.m_search_
->isCanonicalMatch
;
364 m_search_
->isOverlap
= that
.m_search_
->isOverlap
;
365 m_search_
->matchedIndex
= that
.m_search_
->matchedIndex
;
366 m_search_
->matchedLength
= that
.m_search_
->matchedLength
;
367 m_search_
->text
= that
.m_search_
->text
;
368 m_search_
->textLength
= that
.m_search_
->textLength
;
373 void SearchIterator::setMatchLength(int32_t length
)
375 m_search_
->matchedLength
= length
;
378 void SearchIterator::setMatchStart(int32_t position
)
380 m_search_
->matchedIndex
= position
;
383 void SearchIterator::setMatchNotFound()
385 setMatchStart(USEARCH_DONE
);
387 UErrorCode status
= U_ZERO_ERROR
;
388 // by default no errors should be returned here since offsets are within
390 if (m_search_
->isForwardSearching
) {
391 setOffset(m_search_
->textLength
, status
);
394 setOffset(0, status
);
401 #endif /* #if !UCONFIG_NO_COLLATION */