]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/cintltst/reapits.c
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / cintltst / reapits.c
index ee18abfb9664c2e8a4e821ae300c29f1dfef2dd2..d8de2e3a5996dd7fb3bb4ec6bf7edd81a9c439ed 100644 (file)
@@ -1,6 +1,8 @@
+// © 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
@@ -46,23 +56,25 @@ log_data_err("Test Failure at file %s, line %d (Are you missing data?)\n", __FIL
  *         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
 
 
 /**
@@ -158,6 +170,8 @@ static void TestBug4315(void);
 static void TestUTextAPI(void);
 static void TestRefreshInput(void);
 static void TestBug8421(void);
+static void TestBug10815(void);
+static void TestMatchStartLineWithEmptyText(void);
 
 void addURegexTest(TestNode** root);
 
@@ -168,6 +182,8 @@ 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");
 }
 
 /*
@@ -204,7 +220,7 @@ static void TestRegexCAPI(void) {
     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));
@@ -256,7 +272,7 @@ static void TestRegexCAPI(void) {
 
         /* 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*"));
         }
@@ -296,8 +312,8 @@ static void TestRegexCAPI(void) {
         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);
@@ -328,7 +344,7 @@ static void TestRegexCAPI(void) {
     {
         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);
@@ -394,10 +410,10 @@ static void TestRegexCAPI(void) {
         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);
 
@@ -449,10 +465,10 @@ static void TestRegexCAPI(void) {
         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);
@@ -486,9 +502,9 @@ static void TestRegexCAPI(void) {
         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);
@@ -538,7 +554,7 @@ static void TestRegexCAPI(void) {
     {
         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);
 
@@ -621,7 +637,7 @@ static void TestRegexCAPI(void) {
         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);
@@ -634,21 +650,21 @@ static void TestRegexCAPI(void) {
 
         /*  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 */
@@ -684,7 +700,7 @@ static void TestRegexCAPI(void) {
         
         
         /* 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);
@@ -692,7 +708,7 @@ static void TestRegexCAPI(void) {
         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;
         
@@ -816,9 +832,9 @@ static void TestRegexCAPI(void) {
         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);
@@ -826,7 +842,7 @@ static void TestRegexCAPI(void) {
 
         /*  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."));
@@ -834,7 +850,7 @@ static void TestRegexCAPI(void) {
         /* 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."));
@@ -843,7 +859,7 @@ static void TestRegexCAPI(void) {
         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."));
@@ -854,7 +870,7 @@ static void TestRegexCAPI(void) {
          */
         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."));
@@ -869,7 +885,7 @@ static void TestRegexCAPI(void) {
         /* 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."));
@@ -896,12 +912,12 @@ static void TestRegexCAPI(void) {
         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);
@@ -909,7 +925,7 @@ static void TestRegexCAPI(void) {
 
         /*  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);
@@ -917,7 +933,7 @@ static void TestRegexCAPI(void) {
         /* 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));
@@ -937,7 +953,7 @@ static void TestRegexCAPI(void) {
          */
         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> <...>."));
@@ -1001,15 +1017,15 @@ static void TestRegexCAPI(void) {
         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);
@@ -1018,8 +1034,8 @@ static void TestRegexCAPI(void) {
         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); 
@@ -1054,8 +1070,8 @@ static void TestRegexCAPI(void) {
         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);
@@ -1070,7 +1086,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1102,7 +1118,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1160,7 +1176,7 @@ static void TestRegexCAPI(void) {
         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);
@@ -1172,7 +1188,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1184,7 +1200,7 @@ static void TestRegexCAPI(void) {
                 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);
             }
         }
@@ -1193,7 +1209,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1203,7 +1219,7 @@ static void TestRegexCAPI(void) {
             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);
         }
 
@@ -1211,7 +1227,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1222,7 +1238,7 @@ static void TestRegexCAPI(void) {
             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);
         }
 
@@ -1230,7 +1246,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1243,13 +1259,13 @@ static void TestRegexCAPI(void) {
             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);
 
@@ -1257,7 +1273,7 @@ static void TestRegexCAPI(void) {
         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... */
@@ -1271,7 +1287,7 @@ static void TestRegexCAPI(void) {
                 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);
             }
         }
@@ -1315,7 +1331,7 @@ static void TestRegexCAPI(void) {
       *       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;
@@ -1464,8 +1480,8 @@ static void TestUTextAPI(void) {
         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);
@@ -1499,7 +1515,7 @@ static void TestUTextAPI(void) {
         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);
@@ -1602,7 +1618,7 @@ static void TestUTextAPI(void) {
 
         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);
@@ -1698,7 +1714,7 @@ static void TestUTextAPI(void) {
     {
         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);
 
@@ -1751,18 +1767,16 @@ static void TestUTextAPI(void) {
     }
 
     /*
-     *  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);
@@ -1772,58 +1786,38 @@ static void TestUTextAPI(void) {
         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);
-
     }
     
     /*
@@ -1836,12 +1830,13 @@ static void TestUTextAPI(void) {
         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);
@@ -1886,8 +1881,8 @@ static void TestUTextAPI(void) {
         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);
@@ -1926,15 +1921,15 @@ static void TestUTextAPI(void) {
         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);
@@ -1943,8 +1938,8 @@ static void TestUTextAPI(void) {
         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); 
@@ -1967,8 +1962,8 @@ static void TestUTextAPI(void) {
         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);
@@ -2043,7 +2038,7 @@ static void TestUTextAPI(void) {
         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);
@@ -2157,7 +2152,7 @@ static void TestUTextAPI(void) {
 
         /* 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... */
@@ -2266,5 +2261,87 @@ static void TestBug8421(void) {
     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 */