]> granicus.if.org Git - php/commitdiff
Related bug #63588 fix length computation + optimize for speed
authorRemi Collet <remi@php.net>
Mon, 26 Nov 2012 11:59:08 +0000 (12:59 +0100)
committerRemi Collet <remi@php.net>
Mon, 26 Nov 2012 11:59:08 +0000 (12:59 +0100)
Following comment from Yoram "The patch looks fine, except of testing
for true value of utf16 in each iteration."
Also fix the length computation during check phase.

ext/json/json.c

index 270c7cb34682ed24816f05f9ec8adef1df41cb58..fb01529711adc8fdec481df7fda469f201501dda 100644 (file)
@@ -349,12 +349,13 @@ static int json_utf8_to_utf16(unsigned short *utf16, char utf8[], int len) /* {{
        size_t pos = 0, us;
        int j, status;
 
-       for (j=0 ; pos < len ; j++) {
-               us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
-               if (status != SUCCESS) {
-                       return -1;
-               }
-               if (utf16) {
+       if (utf16) {
+               /* really convert the utf8 string */
+               for (j=0 ; pos < len ; j++) {
+                       us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
+                       if (status != SUCCESS) {
+                               return -1;
+                       }
                        /* From http://en.wikipedia.org/wiki/UTF16 */
                        if (us >= 0x10000) {
                                us -= 0x10000;
@@ -364,14 +365,23 @@ static int json_utf8_to_utf16(unsigned short *utf16, char utf8[], int len) /* {{
                                utf16[j] = (unsigned short)us;
                        }
                }
+       } else {
+               /* Only check if utf8 string is valid, and compute utf16 lenght */
+               for (j=0 ; pos < len ; j++) {
+                       us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
+                       if (status != SUCCESS) {
+                               return -1;
+                       }
+                       if (us >= 0x10000) {
+                               j++;
+                       }
+               }
        }
        return j;
 }
 /* }}} */
 
 
-#define REVERSE16(us) (((us & 0xf) << 12) | (((us >> 4) & 0xf) << 8) | (((us >> 8) & 0xf) << 4) | ((us >> 12) & 0xf))
-
 static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
 {
        int pos = 0, ulen = 0;
@@ -516,15 +526,10 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
                                        smart_str_appendc(buf, (unsigned char) us);
                                } else {
                                        smart_str_appendl(buf, "\\u", 2);
-                                       us = REVERSE16(us);
-
-                                       smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
-                                       us >>= 4;
-                                       smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
-                                       us >>= 4;
-                                       smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
-                                       us >>= 4;
-                                       smart_str_appendc(buf, digits[us & ((1 << 4) - 1)]);
+                                       smart_str_appendc(buf, digits[(us & 0xf000) >> 12]);
+                                       smart_str_appendc(buf, digits[(us & 0xf00)  >> 8]);
+                                       smart_str_appendc(buf, digits[(us & 0xf0)   >> 4]);
+                                       smart_str_appendc(buf, digits[(us & 0xf)]);
                                }
                                break;
                }