+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 2004-2013, International Business Machines Corporation and
+ * Copyright (c) 2004-2015, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/********************************************************************************
#include "unicode/uregex.h"
#include "unicode/ustring.h"
#include "unicode/utext.h"
+#include "unicode/utf8.h"
#include "cintltst.h"
+#include "cmemory.h"
-#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
-log_data_err("Failure at file %s, line %d, error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));}}
+#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
+ if (U_FAILURE(status)) { \
+ log_data_err("Failure at file %s:%d - error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status)); \
+ } \
+} UPRV_BLOCK_MACRO_END
-#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \
-log_data_err("Test Failure at file %s, line %d (Are you missing data?)\n", __FILE__, __LINE__);}}
+#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \
+ if ((expr)==FALSE) { \
+ log_err("Test Failure at file %s:%d - ASSERT(%s) failed.\n", __FILE__, __LINE__, #expr); \
+ } \
+} UPRV_BLOCK_MACRO_END
/*
* TEST_SETUP and TEST_TEARDOWN
* Put arbitrary test code between SETUP and TEARDOWN.
* 're" is the compiled, ready-to-go regular expression.
*/
-#define TEST_SETUP(pattern, testString, flags) { \
+#define TEST_SETUP(pattern, testString, flags) UPRV_BLOCK_MACRO_BEGIN { \
UChar *srcString = NULL; \
status = U_ZERO_ERROR; \
re = uregex_openC(pattern, flags, NULL, &status); \
TEST_ASSERT_SUCCESS(status); \
- srcString = (UChar *)malloc((strlen(testString)+2)*sizeof(UChar)); \
- u_uastrncpy(srcString, testString, strlen(testString)+1); \
+ int32_t testStringLen = (int32_t)strlen(testString); \
+ srcString = (UChar *)malloc( (testStringLen + 2) * sizeof(UChar) ); \
+ u_uastrncpy(srcString, testString, testStringLen + 1); \
uregex_setText(re, srcString, -1, &status); \
TEST_ASSERT_SUCCESS(status); \
- if (U_SUCCESS(status)) {
-
+ if (U_SUCCESS(status)) { \
+ UPRV_BLOCK_MACRO_BEGIN {} UPRV_BLOCK_MACRO_END
+
#define TEST_TEARDOWN \
} \
TEST_ASSERT_SUCCESS(status); \
uregex_close(re); \
free(srcString); \
- }
+} UPRV_BLOCK_MACRO_END
/**
static void TestUTextAPI(void);
static void TestRefreshInput(void);
static void TestBug8421(void);
+static void TestBug10815(void);
+static void TestMatchStartLineWithEmptyText(void);
void addURegexTest(TestNode** root);
addTest(root, &TestUTextAPI, "regex/TestUTextAPI");
addTest(root, &TestRefreshInput, "regex/TestRefreshInput");
addTest(root, &TestBug8421, "regex/TestBug8421");
+ addTest(root, &TestBug10815, "regex/TestBug10815");
+ addTest(root, &TestMatchStartLineWithEmptyText, "regex/TestMatchStartLineWithEmptyText");
}
/*
memset(&minus1, -1, sizeof(minus1));
/* Mimimalist open/close */
- u_uastrncpy(pat, "abc*", sizeof(pat)/2);
+ u_uastrncpy(pat, "abc*", UPRV_LENGTHOF(pat));
re = uregex_open(pat, -1, 0, 0, &status);
if (U_FAILURE(status)) {
log_data_err("Failed to open regular expression, %s:%d, error is \"%s\" (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));
/* The TEST_ASSERT_SUCCESS above should change too... */
if(U_SUCCESS(status)) {
- u_uastrncpy(pat, "abc*", sizeof(pat)/2);
+ u_uastrncpy(pat, "abc*", UPRV_LENGTHOF(pat));
TEST_ASSERT(u_strcmp(pat, p) == 0);
TEST_ASSERT(len==(int32_t)strlen("abc*"));
}
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT(clone3 != NULL);
- u_uastrncpy(testString1, "abcccd", sizeof(pat)/2);
- u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2);
+ u_uastrncpy(testString1, "abcccd", UPRV_LENGTHOF(pat));
+ u_uastrncpy(testString2, "xxxabcccd", UPRV_LENGTHOF(pat));
status = U_ZERO_ERROR;
uregex_setText(clone1, testString1, -1, &status);
{
const UChar *resultPat;
int32_t resultLen;
- u_uastrncpy(pat, "hello", sizeof(pat)/2);
+ u_uastrncpy(pat, "hello", UPRV_LENGTHOF(pat));
status = U_ZERO_ERROR;
re = uregex_open(pat, -1, 0, NULL, &status);
resultPat = uregex_pattern(re, &resultLen, &status);
UChar text2[50];
UBool result;
- u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
- u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
+ u_uastrncpy(text1, "abcccd", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "abcccxd", UPRV_LENGTHOF(text2));
status = U_ZERO_ERROR;
- u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ u_uastrncpy(pat, "abc*d", UPRV_LENGTHOF(pat));
re = uregex_open(pat, -1, 0, NULL, &status);
TEST_ASSERT_SUCCESS(status);
const UChar *result;
int32_t textLength;
- u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
- u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
+ u_uastrncpy(text1, "abcccd", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "abcccxd", UPRV_LENGTHOF(text2));
status = U_ZERO_ERROR;
- u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ u_uastrncpy(pat, "abc*d", UPRV_LENGTHOF(pat));
re = uregex_open(pat, -1, 0, NULL, &status);
uregex_setText(re, text1, -1, &status);
int len;
UChar nullString[] = {0,0,0};
- u_uastrncpy(text1, "abcccde", sizeof(text1)/2);
+ u_uastrncpy(text1, "abcccde", UPRV_LENGTHOF(text1));
status = U_ZERO_ERROR;
- u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ u_uastrncpy(pat, "abc*d", UPRV_LENGTHOF(pat));
re = uregex_open(pat, -1, 0, NULL, &status);
uregex_setText(re, text1, -1, &status);
{
UChar text1[50];
UBool result;
- u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2);
+ u_uastrncpy(text1, "012rx5rx890rxrx...", UPRV_LENGTHOF(text1));
status = U_ZERO_ERROR;
re = uregex_openC("rx", 0, NULL, &status);
UChar buf[80];
UBool result;
int32_t resultSz;
- u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2);
+ u_uastrncpy(text1, "noise abc interior def, and this is off the end", UPRV_LENGTHOF(text1));
status = U_ZERO_ERROR;
re = uregex_openC("abc(.*?)def", 0, NULL, &status);
/* Capture Group 0, the full match. Should succeed. */
status = U_ZERO_ERROR;
- resultSz = uregex_group(re, 0, buf, sizeof(buf)/2, &status);
+ resultSz = uregex_group(re, 0, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("abc interior def", buf, TRUE);
TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
/* Capture group #1. Should succeed. */
status = U_ZERO_ERROR;
- resultSz = uregex_group(re, 1, buf, sizeof(buf)/2, &status);
+ resultSz = uregex_group(re, 1, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING(" interior ", buf, TRUE);
TEST_ASSERT(resultSz == (int32_t)strlen(" interior "));
/* Capture group out of range. Error. */
status = U_ZERO_ERROR;
- uregex_group(re, 2, buf, sizeof(buf)/2, &status);
+ uregex_group(re, 2, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR);
/* NULL buffer, pure pre-flight */
/* SetRegion(), getRegion() do something */
- TEST_SETUP(".*", "0123456789ABCDEF", 0)
+ TEST_SETUP(".*", "0123456789ABCDEF", 0);
UChar resultString[40];
TEST_ASSERT(uregex_regionStart(re, &status) == 0);
TEST_ASSERT(uregex_regionEnd(re, &status) == 16);
TEST_ASSERT(uregex_regionStart(re, &status) == 3);
TEST_ASSERT(uregex_regionEnd(re, &status) == 6);
TEST_ASSERT(uregex_findNext(re, &status));
- TEST_ASSERT(uregex_group(re, 0, resultString, sizeof(resultString)/2, &status) == 3)
+ TEST_ASSERT(uregex_group(re, 0, resultString, UPRV_LENGTHOF(resultString), &status) == 3);
TEST_ASSERT_STRING("345", resultString, TRUE);
TEST_TEARDOWN;
UChar replText[80];
UChar buf[80];
int32_t resultSz;
- u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
- u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
+ u_uastrncpy(replText, "<$1>", UPRV_LENGTHOF(replText));
status = U_ZERO_ERROR;
re = uregex_openC("x(.*?)x", 0, NULL, &status);
/* Normal case, with match */
uregex_setText(re, text1, -1, &status);
- resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, TRUE);
TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
/* No match. Text should copy to output with no changes. */
status = U_ZERO_ERROR;
uregex_setText(re, text2, -1, &status);
- resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("No match here.", buf, TRUE);
TEST_ASSERT(resultSz == (int32_t)strlen("No match here."));
status = U_ZERO_ERROR;
uregex_setText(re, text1, -1, &status);
memset(buf, -1, sizeof(buf));
- resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, (int32_t)strlen("Replace <aa> x1x x...x."), &status);
TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
*/
status = U_ZERO_ERROR;
memset(buf, -1, sizeof(buf));
- resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, (int32_t)strlen("Replace <aa> x1x x...x."), &status);
TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
/* Buffer too small by one */
status = U_ZERO_ERROR;
memset(buf, -1, sizeof(buf));
- resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x.")-1, &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, (int32_t)strlen("Replace <aa> x1x x...x.")-1, &status);
TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
TEST_ASSERT_STRING("Replace <aa> x1x x...x", buf, FALSE);
TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
int32_t expectedResultSize2;
int32_t i;
- u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
- u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
- u_uastrncpy(replText2, "<<$1>>", sizeof(replText2)/2);
- expectedResultSize = strlen(expectedResult);
- expectedResultSize2 = strlen(expectedResult2);
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
+ u_uastrncpy(replText, "<$1>", UPRV_LENGTHOF(replText));
+ u_uastrncpy(replText2, "<<$1>>", UPRV_LENGTHOF(replText2));
+ expectedResultSize = (int32_t)strlen(expectedResult);
+ expectedResultSize2 = (int32_t)strlen(expectedResult2);
status = U_ZERO_ERROR;
re = uregex_openC(pattern, 0, NULL, &status);
/* Normal case, with match */
uregex_setText(re, text1, -1, &status);
- resultSize = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
+ resultSize = uregex_replaceAll(re, replText, -1, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING(expectedResult, buf, TRUE);
TEST_ASSERT(resultSize == expectedResultSize);
/* No match. Text should copy to output with no changes. */
status = U_ZERO_ERROR;
uregex_setText(re, text2, -1, &status);
- resultSize = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
+ resultSize = uregex_replaceAll(re, replText, -1, buf, UPRV_LENGTHOF(buf), &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("No match here.", buf, TRUE);
TEST_ASSERT(resultSize == u_strlen(text2));
*/
status = U_ZERO_ERROR;
memset(buf, -1, sizeof(buf));
- resultSize = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status);
+ resultSize = uregex_replaceAll(re, replText, -1, buf, (int32_t)strlen("Replace xaax x1x x...x."), &status);
TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE);
TEST_ASSERT(resultSize == (int32_t)strlen("Replace <aa> <1> <...>."));
re = uregex_openC(".*", 0, 0, &status);
TEST_ASSERT_SUCCESS(status);
- u_uastrncpy(text, "whatever", sizeof(text)/2);
- u_uastrncpy(repl, "some other", sizeof(repl)/2);
+ u_uastrncpy(text, "whatever", UPRV_LENGTHOF(text));
+ u_uastrncpy(repl, "some other", UPRV_LENGTHOF(repl));
uregex_setText(re, text, -1, &status);
/* match covers whole target string */
uregex_find(re, 0, &status);
TEST_ASSERT_SUCCESS(status);
bufPtr = buf;
- bufCap = sizeof(buf) / 2;
+ bufCap = UPRV_LENGTHOF(buf);
uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("some other", buf, TRUE);
uregex_find(re, 0, &status);
TEST_ASSERT_SUCCESS(status);
bufPtr = buf;
- bufCap = sizeof(buf) / 2;
- u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2);
+ bufCap = UPRV_LENGTHOF(buf);
+ u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ \\$ \\abc", UPRV_LENGTHOF(repl));
uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE);
int32_t spaceNeeded;
int32_t sz;
- u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(textToSplit, "first : second: third", UPRV_LENGTHOF(textToSplit));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
status = U_ZERO_ERROR;
re = uregex_openC(":", 0, NULL, &status);
if (U_SUCCESS(status)) {
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 10, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
if(U_SUCCESS(status)) {
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 2, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
int32_t spaceNeeded;
int32_t sz;
- u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2);
+ u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", UPRV_LENGTHOF(textToSplit));
status = U_ZERO_ERROR;
re = uregex_openC("<(.*?)>", 0, NULL, &status);
if(U_SUCCESS(status)) {
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 10, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
TEST_ASSERT_STRING(" third", fields[4], TRUE);
TEST_ASSERT(fields[5] == NULL);
- spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
+ spaceNeeded = (int32_t)strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
TEST_ASSERT(spaceNeeded == requiredCapacity);
}
}
status = U_ZERO_ERROR;
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 2, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
TEST_ASSERT_STRING(" second<tag-b> third", fields[1], TRUE);
TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*)));
- spaceNeeded = strlen("first . second<tag-b> third."); /* "." at NUL positions */
+ spaceNeeded = (int32_t)strlen("first . second<tag-b> third."); /* "." at NUL positions */
TEST_ASSERT(spaceNeeded == requiredCapacity);
}
status = U_ZERO_ERROR;
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 3, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 3, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
TEST_ASSERT_STRING(" second<tag-b> third", fields[2], TRUE);
TEST_ASSERT(!memcmp(&fields[3],&minus1,sizeof(UChar*)));
- spaceNeeded = strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */
+ spaceNeeded = (int32_t)strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */
TEST_ASSERT(spaceNeeded == requiredCapacity);
}
status = U_ZERO_ERROR;
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 5, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 5, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
TEST_ASSERT_STRING(" third", fields[4], TRUE);
TEST_ASSERT(!memcmp(&fields[5],&minus1,sizeof(UChar*)));
- spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
+ spaceNeeded = (int32_t)strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
TEST_ASSERT(spaceNeeded == requiredCapacity);
}
/* Split, end of text is a field delimiter. */
status = U_ZERO_ERROR;
- sz = strlen("first <tag-a> second<tag-b>");
+ sz = (int32_t)strlen("first <tag-a> second<tag-b>");
uregex_setText(re, textToSplit, sz, &status);
TEST_ASSERT_SUCCESS(status);
if(U_SUCCESS(status)) {
memset(fields, -1, sizeof(fields));
numFields =
- uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 9, &status);
+ uregex_split(re, buf, UPRV_LENGTHOF(buf), &requiredCapacity, fields, 9, &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
TEST_ASSERT(fields[5] == NULL);
TEST_ASSERT(fields[8] == NULL);
TEST_ASSERT(!memcmp(&fields[9],&minus1,sizeof(UChar*)));
- spaceNeeded = strlen("first .tag-a. second.tag-b.."); /* "." at NUL positions */
+ spaceNeeded = (int32_t)strlen("first .tag-a. second.tag-b.."); /* "." at NUL positions */
TEST_ASSERT(spaceNeeded == requiredCapacity);
}
}
* to be invoked. The nested '+' operators give exponential time
* behavior with increasing string length.
*/
- TEST_SETUP("((.)+\\2)+x", "aaaaaaaaaaaaaaaaaaab", 0)
+ TEST_SETUP("((.)+\\2)+x", "aaaaaaaaaaaaaaaaaaab", 0);
callBackContext cbInfo = {4, 0, 0};
const void *pContext = &cbInfo;
URegexMatchCallback *returnedFn = &TestCallbackFn;
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT(clone3 != NULL);
- u_uastrncpy(testString1, "abcccd", sizeof(pat)/2);
- u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2);
+ u_uastrncpy(testString1, "abcccd", UPRV_LENGTHOF(pat));
+ u_uastrncpy(testString2, "xxxabcccd", UPRV_LENGTHOF(pat));
status = U_ZERO_ERROR;
uregex_setText(clone1, testString1, -1, &status);
UText *resultText;
const char str_hello[] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00 }; /* hello */
const char str_hel[] = { 0x68, 0x65, 0x6c, 0x00 }; /* hel */
- u_uastrncpy(pat, "hello", sizeof(pat)/2); /* for comparison */
+ u_uastrncpy(pat, "hello", UPRV_LENGTHOF(pat)); /* for comparison */
status = U_ZERO_ERROR;
utext_openUTF8(&patternText, str_hello, -1, &status);
status = U_ZERO_ERROR;
utext_openUTF8(&text1, str_abcccd, -1, &status);
- u_uastrncpy(text2Chars, str_abcccxd, sizeof(text2)/2);
+ u_uastrncpy(text2Chars, str_abcccxd, UPRV_LENGTHOF(text2Chars));
utext_openUChars(&text2, text2Chars, -1, &status);
utext_openUTF8(&patternText, str_abcd, -1, &status);
{
UChar text1[50];
UBool result;
- u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2);
+ u_uastrncpy(text1, "012rx5rx890rxrx...", UPRV_LENGTHOF(text1));
status = U_ZERO_ERROR;
re = uregex_openC("rx", 0, NULL, &status);
}
/*
- * group()
+ * groupUText()
*/
{
UChar text1[80];
UText *actual;
UBool result;
+ int64_t groupLen = 0;
+ UChar groupBuf[20];
- const char str_abcinteriordef[] = { 0x61, 0x62, 0x63, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x66, 0x00 }; /* abc interior def */
- const char str_interior[] = { 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x00 }; /* ' interior ' */
-
-
- u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2);
+ u_uastrncpy(text1, "noise abc interior def, and this is off the end", UPRV_LENGTHOF(text1));
status = U_ZERO_ERROR;
re = uregex_openC("abc(.*?)def", 0, NULL, &status);
result = uregex_find(re, 0, &status);
TEST_ASSERT(result==TRUE);
- /* Capture Group 0, the full match. Should succeed. */
- status = U_ZERO_ERROR;
- actual = uregex_groupUTextDeep(re, 0, NULL, &status);
- TEST_ASSERT_SUCCESS(status);
- TEST_ASSERT_UTEXT(str_abcinteriordef, actual);
- utext_close(actual);
-
/* Capture Group 0 with shallow clone API. Should succeed. */
status = U_ZERO_ERROR;
- {
- int64_t group_len;
- int32_t len16;
- UErrorCode shallowStatus = U_ZERO_ERROR;
- int64_t nativeIndex;
- UChar *groupChars;
- UText groupText = UTEXT_INITIALIZER;
+ actual = uregex_groupUText(re, 0, NULL, &groupLen, &status);
+ TEST_ASSERT_SUCCESS(status);
- actual = uregex_groupUText(re, 0, NULL, &group_len, &status);
- TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(utext_getNativeIndex(actual) == 6); /* index of "abc " within "noise abc ..." */
+ TEST_ASSERT(groupLen == 16); /* length of "abc interior def" */
+ utext_extract(actual, 6 /*start index */, 6+16 /*limit index*/, groupBuf, sizeof(groupBuf), &status);
- nativeIndex = utext_getNativeIndex(actual);
- /* Following returns U_INDEX_OUTOFBOUNDS_ERROR... looks like a bug in ucstrFuncs UTextFuncs [utext.cpp] */
- /* len16 = utext_extract(actual, nativeIndex, nativeIndex + group_len, NULL, 0, &shallowStatus); */
- len16 = (int32_t)group_len;
-
- groupChars = (UChar *)malloc(sizeof(UChar)*(len16+1));
- utext_extract(actual, nativeIndex, nativeIndex + group_len, groupChars, len16+1, &shallowStatus);
-
- utext_openUChars(&groupText, groupChars, len16, &shallowStatus);
-
- TEST_ASSERT_UTEXT(str_abcinteriordef, &groupText);
- utext_close(&groupText);
- free(groupChars);
- }
+ TEST_ASSERT_STRING("abc interior def", groupBuf, TRUE);
utext_close(actual);
/* Capture group #1. Should succeed. */
status = U_ZERO_ERROR;
- actual = uregex_groupUTextDeep(re, 1, NULL, &status);
+
+ actual = uregex_groupUText(re, 1, NULL, &groupLen, &status);
TEST_ASSERT_SUCCESS(status);
- TEST_ASSERT_UTEXT(str_interior, actual);
+ TEST_ASSERT(9 == utext_getNativeIndex(actual)); /* index of " interior " within "noise abc interior def ... " */
+ /* (within the string text1) */
+ TEST_ASSERT(10 == groupLen); /* length of " interior " */
+ utext_extract(actual, 9 /*start index*/, 9+10 /*limit index*/, groupBuf, sizeof(groupBuf), &status);
+ TEST_ASSERT_STRING(" interior ", groupBuf, TRUE);
+
utext_close(actual);
/* Capture group out of range. Error. */
status = U_ZERO_ERROR;
- actual = uregex_groupUTextDeep(re, 2, NULL, &status);
+ actual = uregex_groupUText(re, 2, NULL, &groupLen, &status);
TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR);
- TEST_ASSERT(utext_nativeLength(actual) == 0);
utext_close(actual);
uregex_close(re);
-
}
/*
UText *result;
const char str_Replxxx[] = { 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x3c, 0x61, 0x61, 0x3e, 0x20, 0x78, 0x31, 0x78, 0x20, 0x78, 0x2e, 0x2e, 0x2e, 0x78, 0x2e, 0x00 }; /* Replace <aa> x1x x...x. */
const char str_Nomatchhere[] = { 0x4e, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x00 }; /* No match here. */
- const char str_u00411U00000042a[] = { 0x5c, 0x5c, 0x5c, 0x75, 0x30, 0x30, 0x34, 0x31, 0x24, 0x31, 0x5c, 0x55, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x32, 0x24, 0x5c, 0x61, 0x00 }; /* \\\u0041$1\U00000042$\a */
+ const char str_u00411U00000042a[] = { 0x5c, 0x5c, 0x5c, 0x75, 0x30, 0x30, 0x34, 0x31, 0x24, 0x31,
+ 0x5c, 0x55, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x32, 0x5c, 0x24, 0x5c, 0x61, 0x00 }; /* \\\u0041$1\U00000042\$\a */
const char str_1x[] = { 0x3c, 0x24, 0x31, 0x3e, 0x00 }; /* <$1> */
const char str_ReplaceAaaBax1xxx[] = { 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x5c, 0x41, 0x61, 0x61, 0x42, 0x24, 0x61, 0x20, 0x78, 0x31, 0x78, 0x20, 0x78, 0x2e, 0x2e, 0x2e, 0x78, 0x2e, 0x00 }; /* Replace \AaaB$a x1x x...x. */
status = U_ZERO_ERROR;
- u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
utext_openUTF8(&replText, str_1x, -1, &status);
re = uregex_openC("x(.*?)x", 0, NULL, &status);
const char str_Replaceaa1[] = { 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x3c, 0x61, 0x61, 0x3e, 0x20, 0x3c, 0x31, 0x3e, 0x20, 0x3c, 0x2e, 0x2e, 0x2e, 0x3e, 0x2e, 0x00 }; /* Replace <aa> <1> <...>. */
const char str_Nomatchhere[] = { 0x4e, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x00 }; /* No match here. */
status = U_ZERO_ERROR;
- u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", UPRV_LENGTHOF(text1));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
utext_openUTF8(&replText, str_1, -1, &status);
re = uregex_openC("x(.*?)x", 0, NULL, &status);
re = uregex_openC(".*", 0, 0, &status);
TEST_ASSERT_SUCCESS(status);
- u_uastrncpy(text, "whatever", sizeof(text)/2);
- u_uastrncpy(repl, "some other", sizeof(repl)/2);
+ u_uastrncpy(text, "whatever", UPRV_LENGTHOF(text));
+ u_uastrncpy(repl, "some other", UPRV_LENGTHOF(repl));
uregex_setText(re, text, -1, &status);
/* match covers whole target string */
uregex_find(re, 0, &status);
TEST_ASSERT_SUCCESS(status);
bufPtr = buf;
- bufCap = sizeof(buf) / 2;
+ bufCap = UPRV_LENGTHOF(buf);
uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("some other", buf, TRUE);
uregex_find(re, 0, &status);
TEST_ASSERT_SUCCESS(status);
bufPtr = buf;
- bufCap = sizeof(buf) / 2;
- u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2);
+ bufCap = UPRV_LENGTHOF(buf);
+ u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ \\$ \\abc", UPRV_LENGTHOF(repl));
uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
TEST_ASSERT_SUCCESS(status);
TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE);
int32_t numFields;
int32_t i;
- u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2);
- u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(textToSplit, "first : second: third", UPRV_LENGTHOF(textToSplit));
+ u_uastrncpy(text2, "No match here.", UPRV_LENGTHOF(text2));
status = U_ZERO_ERROR;
re = uregex_openC(":", 0, NULL, &status);
int32_t numFields;
int32_t i;
- u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2);
+ u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", UPRV_LENGTHOF(textToSplit));
status = U_ZERO_ERROR;
re = uregex_openC("<(.*?)>", 0, NULL, &status);
/* Split, end of text is a field delimiter. */
status = U_ZERO_ERROR;
- uregex_setText(re, textToSplit, strlen("first <tag-a> second<tag-b>"), &status);
+ uregex_setText(re, textToSplit, (int32_t)strlen("first <tag-a> second<tag-b>"), &status);
TEST_ASSERT_SUCCESS(status);
/* The TEST_ASSERT_SUCCESS call above should change too... */
uregex_close(re);
}
+static UBool U_CALLCONV FindCallback(const void* context , int64_t matchIndex) {
+ // suppress compiler warnings about unused variables
+ (void)context;
+ (void)matchIndex;
+ return FALSE;
+}
+
+static UBool U_CALLCONV MatchCallback(const void *context, int32_t steps) {
+ // suppress compiler warnings about unused variables
+ (void)context;
+ (void)steps;
+ return FALSE;
+}
+
+static void TestBug10815() {
+ /* Bug 10815: uregex_findNext() does not set U_REGEX_STOPPED_BY_CALLER
+ * when the callback function specified by uregex_setMatchCallback() returns FALSE
+ */
+ URegularExpression *re;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar text[100];
+
+
+ // findNext() with a find progress callback function.
+
+ re = uregex_openC(".z", 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ u_uastrncpy(text, "Hello, World.", UPRV_LENGTHOF(text));
+ uregex_setText(re, text, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_setFindProgressCallback(re, FindCallback, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_findNext(re, &status);
+ TEST_ASSERT(status == U_REGEX_STOPPED_BY_CALLER);
+
+ uregex_close(re);
+
+ // findNext() with a match progress callback function.
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("((xxx)*)*y", 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ // Pattern + this text gives an exponential time match. Without the callback to stop the match,
+ // it will appear to be stuck in a (near) infinite loop.
+ u_uastrncpy(text, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", UPRV_LENGTHOF(text));
+ uregex_setText(re, text, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_setMatchCallback(re, MatchCallback, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_findNext(re, &status);
+ TEST_ASSERT(status == U_REGEX_STOPPED_BY_CALLER);
+
+ uregex_close(re);
+}
+
+static const UChar startLinePattern[] = { 0x5E, 0x78, 0 }; // "^x"
+
+static void TestMatchStartLineWithEmptyText() {
+ UErrorCode status = U_ZERO_ERROR;
+ UText* ut = utext_openUChars(NULL, NULL, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ if (U_SUCCESS(status)) {
+ URegularExpression *re = uregex_open(startLinePattern, -1, 0, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+ if (U_SUCCESS(status)) {
+ uregex_setUText(re, ut, &status);
+ TEST_ASSERT(U_SUCCESS(status));
+ if (U_SUCCESS(status)) {
+ UBool found = uregex_findNext(re, &status);
+ TEST_ASSERT(U_SUCCESS(status) && !found);
+ }
+ uregex_close(re);
+ }
+ utext_close(ut);
+ }
+}
#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */