]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/utf_impl.c
ICU-491.11.2.tar.gz
[apple/icu.git] / icuSources / common / utf_impl.c
index 431b0eb5dad59c285729830971051a70efa5f4a5..7ff990b18a5e168bd1d3939c1ec5225ba541f4b2 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1999-2003, International Business Machines
+*   Copyright (C) 1999-2011, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
 #endif
 
 #include "unicode/utypes.h"
 #endif
 
 #include "unicode/utypes.h"
+#include "unicode/utf.h"
+#include "unicode/utf8.h"
+#include "unicode/utf_old.h"
+#include "uassert.h"
 
 /*
  * This table could be replaced on many machines by
 
 /*
  * This table could be replaced on many machines by
@@ -82,14 +86,37 @@ utf8_errorValue[6]={
     0x3ffffff, 0x7fffffff
 };
 
     0x3ffffff, 0x7fffffff
 };
 
+/*
+ * Handle the non-inline part of the U8_NEXT() macro and its obsolete sibling
+ * UTF8_NEXT_CHAR_SAFE().
+ *
+ * The "strict" parameter controls the error behavior:
+ * <0  "Safe" behavior of U8_NEXT(): All illegal byte sequences yield a negative
+ *     code point result.
+ *  0  Obsolete "safe" behavior of UTF8_NEXT_CHAR_SAFE(..., FALSE):
+ *     All illegal byte sequences yield a positive code point such that this
+ *     result code point would be encoded with the same number of bytes as
+ *     the illegal sequence.
+ * >0  Obsolete "strict" behavior of UTF8_NEXT_CHAR_SAFE(..., TRUE):
+ *     Same as the obsolete "safe" behavior, but non-characters are also treated
+ *     like illegal sequences.
+ *
+ * The special negative (<0) value -2 is used for lenient treatment of surrogate
+ * code points as legal. Some implementations use this for roundtripping of
+ * Unicode 16-bit strings that are not well-formed UTF-16, that is, they
+ * contain unpaired surrogates.
+ *
+ * Note that a UBool is the same as an int8_t.
+ */
 U_CAPI UChar32 U_EXPORT2
 utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c, UBool strict) {
     int32_t i=*pi;
 U_CAPI UChar32 U_EXPORT2
 utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c, UBool strict) {
     int32_t i=*pi;
-    uint8_t count=UTF8_COUNT_TRAIL_BYTES(c);
+    uint8_t count=U8_COUNT_TRAIL_BYTES(c);
+    U_ASSERT(count >= 0 && count <= 5); /* U8_COUNT_TRAIL_BYTES returns value 0...5 */
     if((i)+count<=(length)) {
         uint8_t trail, illegal=0;
 
     if((i)+count<=(length)) {
         uint8_t trail, illegal=0;
 
-        UTF8_MASK_LEAD_BYTE((c), count);
+        U8_MASK_LEAD_BYTE((c), count);
         /* count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff */
         switch(count) {
         /* each branch falls through to the next one */
         /* count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff */
         switch(count) {
         /* each branch falls through to the next one */
@@ -139,12 +166,12 @@ utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c,
 
         /* correct sequence - all trail bytes have (b7..b6)==(10)? */
         /* illegal is also set if count>=4 */
 
         /* correct sequence - all trail bytes have (b7..b6)==(10)? */
         /* illegal is also set if count>=4 */
-        if(illegal || (c)<utf8_minLegal[count] || UTF_IS_SURROGATE(c)) {
+        if(illegal || (c)<utf8_minLegal[count] || (U_IS_SURROGATE(c) && strict!=-2)) {
             /* error handling */
             uint8_t errorCount=count;
             /* don't go beyond this sequence */
             i=*pi;
             /* error handling */
             uint8_t errorCount=count;
             /* don't go beyond this sequence */
             i=*pi;
-            while(count>0 && UTF8_IS_TRAIL(s[i])) {
+            while(count>0 && U8_IS_TRAIL(s[i])) {
                 ++(i);
                 --count;
             }
                 ++(i);
                 --count;
             }
@@ -153,7 +180,7 @@ utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c,
             } else {
                 c=U_SENTINEL;
             }
             } else {
                 c=U_SENTINEL;
             }
-        } else if((strict)>0 && UTF_IS_UNICODE_NONCHAR(c)) {
+        } else if((strict)>0 && U_IS_UNICODE_NONCHAR(c)) {
             /* strict: forbid non-characters like U+fffe */
             c=utf8_errorValue[count];
         }
             /* strict: forbid non-characters like U+fffe */
             c=utf8_errorValue[count];
         }
@@ -161,7 +188,7 @@ utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c,
         /* error handling */
         int32_t i0=i;
         /* don't just set (i)=(length) in case there is an illegal sequence */
         /* error handling */
         int32_t i0=i;
         /* don't just set (i)=(length) in case there is an illegal sequence */
-        while((i)<(length) && UTF8_IS_TRAIL(s[i])) {
+        while((i)<(length) && U8_IS_TRAIL(s[i])) {
             ++(i);
         }
         if(strict>=0) {
             ++(i);
         }
         if(strict>=0) {
@@ -235,7 +262,7 @@ utf8_prevCharSafeBody(const uint8_t *s, int32_t start, int32_t *pi, UChar32 c, U
             } else {
                 return U_SENTINEL;
             }
             } else {
                 return U_SENTINEL;
             }
-            break;
+            /*break;*/
         }
 
         /* read another previous byte */
         }
 
         /* read another previous byte */
@@ -243,14 +270,14 @@ utf8_prevCharSafeBody(const uint8_t *s, int32_t start, int32_t *pi, UChar32 c, U
         if((uint8_t)(b-0x80)<0x7e) { /* 0x80<=b<0xfe */
             if(b&0x40) {
                 /* lead byte, this will always end the loop */
         if((uint8_t)(b-0x80)<0x7e) { /* 0x80<=b<0xfe */
             if(b&0x40) {
                 /* lead byte, this will always end the loop */
-                uint8_t shouldCount=UTF8_COUNT_TRAIL_BYTES(b);
+                uint8_t shouldCount=U8_COUNT_TRAIL_BYTES(b);
 
                 if(count==shouldCount) {
                     /* set the new position */
                     *pi=i;
 
                 if(count==shouldCount) {
                     /* set the new position */
                     *pi=i;
-                    UTF8_MASK_LEAD_BYTE(b, count);
+                    U8_MASK_LEAD_BYTE(b, count);
                     c|=(UChar32)b<<shift;
                     c|=(UChar32)b<<shift;
-                    if(count>=4 || c>0x10ffff || c<utf8_minLegal[count] || UTF_IS_SURROGATE(c) || (strict>0 && UTF_IS_UNICODE_NONCHAR(c))) {
+                    if(count>=4 || c>0x10ffff || c<utf8_minLegal[count] || (U_IS_SURROGATE(c) && strict!=-2) || (strict>0 && U_IS_UNICODE_NONCHAR(c))) {
                         /* illegal sequence or (strict and non-character) */
                         if(count>=4) {
                             count=3;
                         /* illegal sequence or (strict and non-character) */
                         if(count>=4) {
                             count=3;
@@ -329,7 +356,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i) {
         if((uint8_t)(b-0x80)>=0x7e) { /* not 0x80<=b<0xfe */
             break;
         } else if(b>=0xc0) {
         if((uint8_t)(b-0x80)>=0x7e) { /* not 0x80<=b<0xfe */
             break;
         } else if(b>=0xc0) {
-            if(UTF8_COUNT_TRAIL_BYTES(b)>=(i-I)) {
+            if(U8_COUNT_TRAIL_BYTES(b)>=(i-I)) {
                 return I;
             } else {
                 break;
                 return I;
             } else {
                 break;