+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*****************************************************************************
-* Copyright (C) 2001-2010, International Business Machines orporation
+* Copyright (C) 2001-2016, International Business Machines orporation
* and others. All Rights Reserved.
****************************************************************************/
#include "unicode/stsearch.h"
#include "unicode/ustring.h"
#include "unicode/schriter.h"
+#include "cmemory.h"
#include <string.h>
#include <stdio.h>
UBool StringSearchTest::assertEqualWithStringSearch(StringSearch *strsrch,
const SearchData *search)
{
- int count = 0;
- UErrorCode status = U_ZERO_ERROR;
- int32_t matchindex = search->offset[count];
- UnicodeString matchtext;
-
+ int32_t count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t matchindex = search->offset[count];
+ UnicodeString matchtext;
+ int32_t matchlength;
+
strsrch->setAttribute(USEARCH_ELEMENT_COMPARISON, search->elemCompare, status);
if (U_FAILURE(status)) {
errln("Error setting USEARCH_ELEMENT_COMPARISON attribute %s", u_errorName(status));
strsrch->getMatchedLength() != 0) {
errln("Error with the initialization of match start and length");
}
- // start of following matches
+
+ // start of next matches
while (U_SUCCESS(status) && matchindex >= 0) {
- int32_t matchlength = search->size[count];
+ matchlength = search->size[count];
strsrch->next(status);
if (matchindex != strsrch->getMatchedStart() ||
matchlength != strsrch->getMatchedLength()) {
char *str = toCharString(strsrch->getText());
errln("Text: %s", str);
str = toCharString(strsrch->getPattern());
- infoln("Pattern: %s", str);
- infoln("Error following match found at idx,len %d,%d; expected %d,%d",
+ errln("Pattern: %s", str);
+ errln("Error next match found at %d (len:%d); expected %d (len:%d)",
strsrch->getMatchedStart(), strsrch->getMatchedLength(),
matchindex, matchlength);
return FALSE;
matchindex + matchlength,
matchtext, 0,
matchtext.length())) {
- errln("Error getting following matched text");
+ errln("Error getting next matched text");
}
matchindex = search->offset[count];
errln("Text: %s", str);
str = toCharString(strsrch->getPattern());
errln("Pattern: %s", str);
- errln("Error following match found at %d %d",
+ errln("Error next match found at %d (len:%d); expected <NO MATCH>",
strsrch->getMatchedStart(), strsrch->getMatchedLength());
return FALSE;
}
- // start of preceding matches
+
+ // start of previous matches
count = count == 0 ? 0 : count - 1;
matchindex = search->offset[count];
while (U_SUCCESS(status) && matchindex >= 0) {
- int32_t matchlength = search->size[count];
+ matchlength = search->size[count];
strsrch->previous(status);
if (matchindex != strsrch->getMatchedStart() ||
matchlength != strsrch->getMatchedLength()) {
errln("Text: %s", str);
str = toCharString(strsrch->getPattern());
errln("Pattern: %s", str);
- errln("Error following match found at %d %d",
- strsrch->getMatchedStart(), strsrch->getMatchedLength());
+ errln("Error previous match found at %d (len:%d); expected %d (len:%d)",
+ strsrch->getMatchedStart(), strsrch->getMatchedLength(),
+ matchindex, matchlength);
return FALSE;
}
matchindex + matchlength,
matchtext, 0,
matchtext.length())) {
- errln("Error getting following matched text");
+ errln("Error getting previous matched text");
}
matchindex = count > 0 ? search->offset[count - 1] : -1;
if (strsrch->getMatchedStart() != USEARCH_DONE ||
strsrch->getMatchedLength() != 0) {
char *str = toCharString(strsrch->getText());
- errln("Text: %s", str);
+ errln("Text: %s", str);
+ str = toCharString(strsrch->getPattern());
+ errln("Pattern: %s", str);
+ errln("Error previous match found at %d (len:%d); expected <NO MATCH>",
+ strsrch->getMatchedStart(), strsrch->getMatchedLength());
+ return FALSE;
+ }
+
+ int32_t nextStart;
+ UBool isOverlap = (strsrch->getAttribute(USEARCH_OVERLAP) == USEARCH_ON);
+
+ // start of following matches
+ count = 0;
+ matchindex = search->offset[count];
+ nextStart = 0;
+
+ while (TRUE) {
+ strsrch->following(nextStart, status);
+
+ if (matchindex < 0) {
+ if (strsrch->getMatchedStart() != USEARCH_DONE ||
+ strsrch->getMatchedLength() != 0) {
+ char *str = toCharString(strsrch->getText());
+ errln("Text: %s", str);
+ str = toCharString(strsrch->getPattern());
+ errln("Pattern: %s", str);
+ errln("Error following match starting at %d (overlap:%d) found at %d (len:%d); expected <NO MATCH>",
+ nextStart, isOverlap,
+ strsrch->getMatchedStart(), strsrch->getMatchedLength());
+ return FALSE;
+ }
+ // no more matches
+ break;
+ }
+
+ matchlength = search->size[count];
+ if (strsrch->getMatchedStart() != matchindex
+ || strsrch->getMatchedLength() != matchlength
+ || U_FAILURE(status)) {
+ char *str = toCharString(strsrch->getText());
+ errln("Text: %s\n", str);
str = toCharString(strsrch->getPattern());
- errln("Pattern: %s", str);
- errln("Error following match found at %d %d",
- strsrch->getMatchedStart(), strsrch->getMatchedLength());
+ errln("Pattern: %s\n", str);
+ errln("Error following match starting at %d (overlap: %d) found at %d (len:%d); expected %d (len:%d)\n",
+ nextStart, isOverlap,
+ strsrch->getMatchedStart(), strsrch->getMatchedLength(),
+ matchindex, matchlength);
return FALSE;
+ }
+
+ if (isOverlap || strsrch->getMatchedLength() == 0) {
+ nextStart = strsrch->getMatchedStart() + 1;
+ } else {
+ nextStart = strsrch->getMatchedStart() + strsrch->getMatchedLength();
+ }
+
+ count++;
+ matchindex = search->offset[count];
+ }
+
+ // start preceding matches
+ count = -1; // last non-negative offset index, could be -1 if no match
+ while (search->offset[count + 1] >= 0) {
+ count++;
}
+ nextStart = strsrch->getText().length();
+
+ while (TRUE) {
+ strsrch->preceding(nextStart, status);
+
+ if (count < 0) {
+ if (strsrch->getMatchedStart() != USEARCH_DONE || strsrch->getMatchedLength() != 0) {
+ char *str = toCharString(strsrch->getText());
+ errln("Text: %s\n", str);
+ str = toCharString(strsrch->getPattern());
+ errln("Pattern: %s\n", str);
+ errln("Error preceding match starting at %d (overlap: %d) found at %d (len:%d); expected <NO MATCH>\n",
+ nextStart, isOverlap,
+ strsrch->getMatchedStart(),
+ strsrch->getMatchedLength());
+ return FALSE;
+ }
+ // no more matches
+ break;
+ }
+
+ matchindex = search->offset[count];
+ matchlength = search->size[count];
+ if (strsrch->getMatchedStart() != matchindex
+ || strsrch->getMatchedLength() != matchlength
+ || U_FAILURE(status)) {
+ char *str = toCharString(strsrch->getText());
+ errln("Text: %s\n", str);
+ str = toCharString(strsrch->getPattern());
+ errln("Pattern: %s\n", str);
+ errln("Error preceding match starting at %d (overlap: %d) found at %d (len:%d); expected %d (len:%d)\n",
+ nextStart, isOverlap,
+ strsrch->getMatchedStart(), strsrch->getMatchedLength(),
+ matchindex, matchlength);
+ return FALSE;
+ }
+
+ nextStart = matchindex;
+ count--;
+ }
+
strsrch->setAttribute(USEARCH_ELEMENT_COMPARISON, USEARCH_STANDARD_ELEMENT_COMPARISON, status);
return TRUE;
}
}
delete result;
- text.append(0, 0x1);
+ // No-op: text.append(0, 0x1); -- what was intended here?
status = U_ZERO_ERROR;
result = new StringSearch(pattern, text, NULL, NULL, status);
if (U_SUCCESS(status)) {
if (U_FAILURE(status)) {
errln("Error opening rule based collator %s", u_errorName(status));
delete strsrch;
- if (tailored != NULL) {
- delete tailored;
- }
+ delete tailored;
return;
}
if (U_FAILURE(status) || (*strsrch->getCollator()) != (*tailored)) {
errln("Error setting rule based collator");
delete strsrch;
- if (tailored != NULL) {
- delete tailored;
- }
+ delete tailored;
}
strsrch->reset();
if (!assertEqualWithStringSearch(strsrch, &COLLATOR[1])) {
delete strsrch;
- if (tailored != NULL) {
- delete tailored;
- }
+ delete tailored;
return;
}
if (U_FAILURE(status) || (*strsrch->getCollator()) != (*m_en_us_)) {
errln("Error setting rule based collator");
delete strsrch;
- if (tailored != NULL) {
- delete tailored;
- }
+ delete tailored;
}
if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
errln("Error searching collator test");
}
delete strsrch;
- if (tailored != NULL) {
- delete tailored;
- }
+ delete tailored;
}
void StringSearchTest::TestPattern()
search.reset();
// comparing constructors
- for (i = 0; i < (int)(sizeof(expected) / sizeof(expected[0])); i ++) {
+ for (i = 0; i < UPRV_LENGTHOF(expected); i ++) {
if (search.next(status) != expected[i]) {
errln("Error getting next match");
}
if (search.next(status) != USEARCH_DONE) {
errln("Error should have reached the end of the iteration");
}
- for (i = sizeof(expected) / sizeof(expected[0]) - 1; i >= 0; i --) {
+ for (i = UPRV_LENGTHOF(expected) - 1; i >= 0; i --) {
if (search.previous(status) != expected[i]) {
errln("Error getting previous match");
}