LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 4 215 1.9 %
Date: 2017-07-14 16:53:18 Functions: 1 23 4.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : 
       9             : #include "SkUtils.h"
      10             : 
      11           0 : void sk_memset16(uint16_t buffer[], uint16_t value, int count) {
      12           0 :     for (int i = 0; i < count; i++) {
      13           0 :         buffer[i] = value;
      14             :     }
      15           0 : }
      16       19695 : void sk_memset32(uint32_t buffer[], uint32_t value, int count) {
      17    20207193 :     for (int i = 0; i < count; i++) {
      18    20187498 :         buffer[i] = value;
      19             :     }
      20       19695 : }
      21           0 : void sk_memset64(uint64_t buffer[], uint64_t value, int count) {
      22           0 :     for (int i = 0; i < count; i++) {
      23           0 :         buffer[i] = value;
      24             :     }
      25           0 : }
      26             : 
      27             : /*  0xxxxxxx    1 total
      28             :     10xxxxxx    // never a leading byte
      29             :     110xxxxx    2 total
      30             :     1110xxxx    3 total
      31             :     11110xxx    4 total
      32             : 
      33             :     11 10 01 01 xx xx xx xx 0...
      34             :     0xE5XX0000
      35             :     0xE5 << 24
      36             : */
      37             : 
      38           0 : static bool utf8_byte_is_valid(uint8_t c) {
      39           0 :     return c < 0xF5 && (c & 0xFE) != 0xC0;
      40             : }
      41           0 : static bool utf8_byte_is_continuation(uint8_t c) {
      42           0 :     return  (c & 0xC0) == 0x80;
      43             : }
      44           0 : static bool utf8_byte_is_leading_byte(uint8_t c) {
      45           0 :     return utf8_byte_is_valid(c) && !utf8_byte_is_continuation(c);
      46             : }
      47             : 
      48             : #ifdef SK_DEBUG
      49           0 :     static void assert_utf8_leadingbyte(unsigned c) {
      50           0 :         SkASSERT(utf8_byte_is_leading_byte(SkToU8(c)));
      51           0 :     }
      52             : 
      53           0 :     int SkUTF8_LeadByteToCount(unsigned c) {
      54           0 :         assert_utf8_leadingbyte(c);
      55           0 :         return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1;
      56             :     }
      57             : #else
      58             :     #define assert_utf8_leadingbyte(c)
      59             : #endif
      60             : 
      61             : /**
      62             :  * @returns -1  iff invalid UTF8 byte,
      63             :  *           0  iff UTF8 continuation byte,
      64             :  *           1  iff ASCII byte,
      65             :  *           2  iff leading byte of 2-byte sequence,
      66             :  *           3  iff leading byte of 3-byte sequence, and
      67             :  *           4  iff leading byte of 4-byte sequence.
      68             :  *
      69             :  * I.e.: if return value > 0, then gives length of sequence.
      70             : */
      71           0 : static int utf8_byte_type(uint8_t c) {
      72           0 :     if (c < 0x80) {
      73           0 :         return 1;
      74           0 :     } else if (c < 0xC0) {
      75           0 :         return 0;
      76           0 :     } else if (c < 0xF5 && (c & 0xFE) != 0xC0) { // "octet values C0, C1, F5 to FF never appear"
      77           0 :         return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
      78             :     } else {
      79           0 :         return -1;
      80             :     }
      81             : }
      82           0 : static bool utf8_type_is_valid_leading_byte(int type) { return type > 0; }
      83             : 
      84           0 : int SkUTF8_CountUnichars(const char utf8[]) {
      85           0 :     SkASSERT(utf8);
      86             : 
      87           0 :     int count = 0;
      88             : 
      89             :     for (;;) {
      90           0 :         int c = *(const uint8_t*)utf8;
      91           0 :         if (c == 0) {
      92           0 :             break;
      93             :         }
      94           0 :         utf8 += SkUTF8_LeadByteToCount(c);
      95           0 :         count += 1;
      96           0 :     }
      97           0 :     return count;
      98             : }
      99             : 
     100             : // SAFE: returns -1 if invalid UTF-8
     101           0 : int SkUTF8_CountUnicharsWithError(const char utf8[], size_t byteLength) {
     102           0 :     SkASSERT(utf8 || 0 == byteLength);
     103             : 
     104           0 :     int         count = 0;
     105           0 :     const char* stop = utf8 + byteLength;
     106             : 
     107           0 :     while (utf8 < stop) {
     108           0 :         int type = utf8_byte_type(*(const uint8_t*)utf8);
     109           0 :         SkASSERT(type >= -1 && type <= 4);
     110           0 :         if (!utf8_type_is_valid_leading_byte(type) ||
     111           0 :             utf8 + type > stop) {  // Sequence extends beyond end.
     112           0 :             return -1;
     113             :         }
     114           0 :         while(type-- > 1) {
     115           0 :             ++utf8;
     116           0 :             if (!utf8_byte_is_continuation(*(const uint8_t*)utf8)) {
     117           0 :                 return -1;
     118             :             }
     119             :         }
     120           0 :         ++utf8;
     121           0 :         ++count;
     122             :     }
     123           0 :     return count;
     124             : }
     125             : 
     126           0 : SkUnichar SkUTF8_ToUnichar(const char utf8[]) {
     127           0 :     SkASSERT(utf8);
     128             : 
     129           0 :     const uint8_t*  p = (const uint8_t*)utf8;
     130           0 :     int             c = *p;
     131           0 :     int             hic = c << 24;
     132             : 
     133           0 :     assert_utf8_leadingbyte(c);
     134             : 
     135           0 :     if (hic < 0) {
     136           0 :         uint32_t mask = (uint32_t)~0x3F;
     137           0 :         hic = SkLeftShift(hic, 1);
     138           0 :         do {
     139           0 :             c = (c << 6) | (*++p & 0x3F);
     140           0 :             mask <<= 5;
     141             :         } while ((hic = SkLeftShift(hic, 1)) < 0);
     142           0 :         c &= ~mask;
     143             :     }
     144           0 :     return c;
     145             : }
     146             : 
     147             : // SAFE: returns -1 on invalid UTF-8 sequence.
     148           0 : SkUnichar SkUTF8_NextUnicharWithError(const char** ptr, const char* end) {
     149           0 :     SkASSERT(ptr && *ptr);
     150           0 :     SkASSERT(*ptr < end);
     151           0 :     const uint8_t*  p = (const uint8_t*)*ptr;
     152           0 :     int             c = *p;
     153           0 :     int             hic = c << 24;
     154             : 
     155           0 :     if (!utf8_byte_is_leading_byte(c)) {
     156           0 :         return -1;
     157             :     }
     158           0 :     if (hic < 0) {
     159           0 :         uint32_t mask = (uint32_t)~0x3F;
     160           0 :         hic = SkLeftShift(hic, 1);
     161           0 :         do {
     162           0 :             ++p;
     163           0 :             if (p >= (const uint8_t*)end) {
     164           0 :                 return -1;
     165             :             }
     166             :             // check before reading off end of array.
     167           0 :             uint8_t nextByte = *p;
     168           0 :             if (!utf8_byte_is_continuation(nextByte)) {
     169           0 :                 return -1;
     170             :             }
     171           0 :             c = (c << 6) | (nextByte & 0x3F);
     172           0 :             mask <<= 5;
     173             :         } while ((hic = SkLeftShift(hic, 1)) < 0);
     174           0 :         c &= ~mask;
     175             :     }
     176           0 :     *ptr = (char*)p + 1;
     177           0 :     return c;
     178             : }
     179             : 
     180           0 : SkUnichar SkUTF8_NextUnichar(const char** ptr) {
     181           0 :     SkASSERT(ptr && *ptr);
     182             : 
     183           0 :     const uint8_t*  p = (const uint8_t*)*ptr;
     184           0 :     int             c = *p;
     185           0 :     int             hic = c << 24;
     186             : 
     187           0 :     assert_utf8_leadingbyte(c);
     188             : 
     189           0 :     if (hic < 0) {
     190           0 :         uint32_t mask = (uint32_t)~0x3F;
     191           0 :         hic = SkLeftShift(hic, 1);
     192           0 :         do {
     193           0 :             c = (c << 6) | (*++p & 0x3F);
     194           0 :             mask <<= 5;
     195             :         } while ((hic = SkLeftShift(hic, 1)) < 0);
     196           0 :         c &= ~mask;
     197             :     }
     198           0 :     *ptr = (char*)p + 1;
     199           0 :     return c;
     200             : }
     201             : 
     202           0 : SkUnichar SkUTF8_PrevUnichar(const char** ptr) {
     203           0 :     SkASSERT(ptr && *ptr);
     204             : 
     205           0 :     const char* p = *ptr;
     206             : 
     207           0 :     if (*--p & 0x80) {
     208           0 :         while (*--p & 0x40) {
     209             :             ;
     210             :         }
     211             :     }
     212             : 
     213           0 :     *ptr = (char*)p;
     214           0 :     return SkUTF8_NextUnichar(&p);
     215             : }
     216             : 
     217           0 : size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) {
     218           0 :     if ((uint32_t)uni > 0x10FFFF) {
     219           0 :         SkDEBUGFAIL("bad unichar");
     220           0 :         return 0;
     221             :     }
     222             : 
     223           0 :     if (uni <= 127) {
     224           0 :         if (utf8) {
     225           0 :             *utf8 = (char)uni;
     226             :         }
     227           0 :         return 1;
     228             :     }
     229             : 
     230             :     char    tmp[4];
     231           0 :     char*   p = tmp;
     232           0 :     size_t  count = 1;
     233             : 
     234           0 :     SkDEBUGCODE(SkUnichar orig = uni;)
     235             : 
     236           0 :     while (uni > 0x7F >> count) {
     237           0 :         *p++ = (char)(0x80 | (uni & 0x3F));
     238           0 :         uni >>= 6;
     239           0 :         count += 1;
     240             :     }
     241             : 
     242           0 :     if (utf8) {
     243           0 :         p = tmp;
     244           0 :         utf8 += count;
     245           0 :         while (p < tmp + count - 1) {
     246           0 :             *--utf8 = *p++;
     247             :         }
     248           0 :         *--utf8 = (char)(~(0xFF >> count) | uni);
     249             :     }
     250             : 
     251           0 :     SkASSERT(utf8 == nullptr || orig == SkUTF8_ToUnichar(utf8));
     252           0 :     return count;
     253             : }
     254             : 
     255             : ///////////////////////////////////////////////////////////////////////////////
     256             : 
     257           0 : int SkUTF16_CountUnichars(const uint16_t src[]) {
     258           0 :     SkASSERT(src);
     259             : 
     260           0 :     int count = 0;
     261             :     unsigned c;
     262           0 :     while ((c = *src++) != 0) {
     263           0 :         SkASSERT(!SkUTF16_IsLowSurrogate(c));
     264           0 :         if (SkUTF16_IsHighSurrogate(c)) {
     265           0 :             c = *src++;
     266           0 :             SkASSERT(SkUTF16_IsLowSurrogate(c));
     267             :         }
     268           0 :         count += 1;
     269             :     }
     270           0 :     return count;
     271             : }
     272             : 
     273           0 : int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) {
     274           0 :     SkASSERT(src);
     275             : 
     276           0 :     const uint16_t* stop = src + numberOf16BitValues;
     277           0 :     int count = 0;
     278           0 :     while (src < stop) {
     279           0 :         unsigned c = *src++;
     280           0 :         SkASSERT(!SkUTF16_IsLowSurrogate(c));
     281           0 :         if (SkUTF16_IsHighSurrogate(c)) {
     282           0 :             SkASSERT(src < stop);
     283           0 :             c = *src++;
     284           0 :             SkASSERT(SkUTF16_IsLowSurrogate(c));
     285             :         }
     286           0 :         count += 1;
     287             :     }
     288           0 :     return count;
     289             : }
     290             : 
     291           0 : SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) {
     292           0 :     SkASSERT(srcPtr && *srcPtr);
     293             : 
     294           0 :     const uint16_t* src = *srcPtr;
     295           0 :     SkUnichar       c = *src++;
     296             : 
     297           0 :     SkASSERT(!SkUTF16_IsLowSurrogate(c));
     298           0 :     if (SkUTF16_IsHighSurrogate(c)) {
     299           0 :         unsigned c2 = *src++;
     300           0 :         SkASSERT(SkUTF16_IsLowSurrogate(c2));
     301             : 
     302             :         // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000
     303             :         // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF)
     304           0 :         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
     305             :     }
     306           0 :     *srcPtr = src;
     307           0 :     return c;
     308             : }
     309             : 
     310           0 : SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) {
     311           0 :     SkASSERT(srcPtr && *srcPtr);
     312             : 
     313           0 :     const uint16_t* src = *srcPtr;
     314           0 :     SkUnichar       c = *--src;
     315             : 
     316           0 :     SkASSERT(!SkUTF16_IsHighSurrogate(c));
     317           0 :     if (SkUTF16_IsLowSurrogate(c)) {
     318           0 :         unsigned c2 = *--src;
     319           0 :         SkASSERT(SkUTF16_IsHighSurrogate(c2));
     320           0 :         c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00);
     321             :     }
     322           0 :     *srcPtr = src;
     323           0 :     return c;
     324             : }
     325             : 
     326           0 : size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) {
     327           0 :     SkASSERT((unsigned)uni <= 0x10FFFF);
     328             : 
     329           0 :     int extra = (uni > 0xFFFF);
     330             : 
     331           0 :     if (dst) {
     332           0 :         if (extra) {
     333             :             // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10));
     334             :             // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64));
     335           0 :             dst[0] = SkToU16((0xD800 - 64) + (uni >> 10));
     336           0 :             dst[1] = SkToU16(0xDC00 | (uni & 0x3FF));
     337             : 
     338           0 :             SkASSERT(SkUTF16_IsHighSurrogate(dst[0]));
     339           0 :             SkASSERT(SkUTF16_IsLowSurrogate(dst[1]));
     340             :         } else {
     341           0 :             dst[0] = SkToU16(uni);
     342           0 :             SkASSERT(!SkUTF16_IsHighSurrogate(dst[0]));
     343           0 :             SkASSERT(!SkUTF16_IsLowSurrogate(dst[0]));
     344             :         }
     345             :     }
     346           0 :     return 1 + extra;
     347             : }
     348             : 
     349           0 : size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
     350             :                       char utf8[]) {
     351           0 :     SkASSERT(numberOf16BitValues >= 0);
     352           0 :     if (numberOf16BitValues <= 0) {
     353           0 :         return 0;
     354             :     }
     355             : 
     356           0 :     SkASSERT(utf16 != nullptr);
     357             : 
     358           0 :     const uint16_t* stop = utf16 + numberOf16BitValues;
     359           0 :     size_t          size = 0;
     360             : 
     361           0 :     if (utf8 == nullptr) {    // just count
     362           0 :         while (utf16 < stop) {
     363           0 :             size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), nullptr);
     364             :         }
     365             :     } else {
     366           0 :         char* start = utf8;
     367           0 :         while (utf16 < stop) {
     368           0 :             utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8);
     369             :         }
     370           0 :         size = utf8 - start;
     371             :     }
     372           0 :     return size;
     373             : }

Generated by: LCOV version 1.13