gfx/skia/trunk/src/core/SkPackBits.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2011 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     8 #include "SkPackBits.h"
    10 #define GATHER_STATSx
    12 static inline void small_memcpy(void* SK_RESTRICT dst,
    13                                 const void* SK_RESTRICT src, int n) {
    14     SkASSERT(n > 0 && n <= 15);
    15     uint8_t* d = (uint8_t*)dst;
    16     const uint8_t* s = (const uint8_t*)src;
    17     switch (n) {
    18         case 15: *d++ = *s++;
    19         case 14: *d++ = *s++;
    20         case 13: *d++ = *s++;
    21         case 12: *d++ = *s++;
    22         case 11: *d++ = *s++;
    23         case 10: *d++ = *s++;
    24         case  9: *d++ = *s++;
    25         case  8: *d++ = *s++;
    26         case  7: *d++ = *s++;
    27         case  6: *d++ = *s++;
    28         case  5: *d++ = *s++;
    29         case  4: *d++ = *s++;
    30         case  3: *d++ = *s++;
    31         case  2: *d++ = *s++;
    32         case  1: *d++ = *s++;
    33         case  0: break;
    34     }
    35 }
    37 static inline void small_memset(void* dst, uint8_t value, int n) {
    38     SkASSERT(n > 0 && n <= 15);
    39     uint8_t* d = (uint8_t*)dst;
    40     switch (n) {
    41         case 15: *d++ = value;
    42         case 14: *d++ = value;
    43         case 13: *d++ = value;
    44         case 12: *d++ = value;
    45         case 11: *d++ = value;
    46         case 10: *d++ = value;
    47         case  9: *d++ = value;
    48         case  8: *d++ = value;
    49         case  7: *d++ = value;
    50         case  6: *d++ = value;
    51         case  5: *d++ = value;
    52         case  4: *d++ = value;
    53         case  3: *d++ = value;
    54         case  2: *d++ = value;
    55         case  1: *d++ = value;
    56         case  0: break;
    57     }
    58 }
    60 // can we do better for small counts with our own inlined memcpy/memset?
    62 #define PB_MEMSET(addr, value, count)       \
    63 do {                                        \
    64 if ((count) > 15) {                     \
    65 memset(addr, value, count);         \
    66 } else {                                \
    67 small_memset(addr, value, count);   \
    68 }                                       \
    69 } while (0)
    71 #define PB_MEMCPY(dst, src, count)      \
    72 do {                                    \
    73     if ((count) > 15) {                 \
    74         memcpy(dst, src, count);        \
    75     } else {                            \
    76         small_memcpy(dst, src, count);  \
    77     }                                   \
    78 } while (0)
    80 ///////////////////////////////////////////////////////////////////////////////
    82 #ifdef GATHER_STATS
    83     static int gMemSetBuckets[129];
    84     static int gMemCpyBuckets[129];
    85     static int gCounter;
    87 static void register_memset_count(int n) {
    88     SkASSERT((unsigned)n <= 128);
    89     gMemSetBuckets[n] += 1;
    90     gCounter += 1;
    92     if ((gCounter & 0xFF) == 0) {
    93         SkDebugf("----- packbits memset stats: ");
    94         for (size_t i = 0; i < SK_ARRAY_COUNT(gMemSetBuckets); i++) {
    95             if (gMemSetBuckets[i]) {
    96                 SkDebugf(" %d:%d", i, gMemSetBuckets[i]);
    97             }
    98         }
    99     }
   100 }
   101 static void register_memcpy_count(int n) {
   102     SkASSERT((unsigned)n <= 128);
   103     gMemCpyBuckets[n] += 1;
   104     gCounter += 1;
   106     if ((gCounter & 0x1FF) == 0) {
   107         SkDebugf("----- packbits memcpy stats: ");
   108         for (size_t i = 0; i < SK_ARRAY_COUNT(gMemCpyBuckets); i++) {
   109             if (gMemCpyBuckets[i]) {
   110                 SkDebugf(" %d:%d", i, gMemCpyBuckets[i]);
   111             }
   112         }
   113     }
   114 }
   115 #else
   116 #define register_memset_count(n)
   117 #define register_memcpy_count(n)
   118 #endif
   121 ///////////////////////////////////////////////////////////////////////////////
   123 size_t SkPackBits::ComputeMaxSize16(int count) {
   124     // worst case is the number of 16bit values (times 2) +
   125     // 1 byte per (up to) 128 entries.
   126     return ((count + 127) >> 7) + (count << 1);
   127 }
   129 size_t SkPackBits::ComputeMaxSize8(int count) {
   130     // worst case is the number of 8bit values + 1 byte per (up to) 128 entries.
   131     return ((count + 127) >> 7) + count;
   132 }
   134 static uint8_t* flush_same16(uint8_t dst[], uint16_t value, int count) {
   135     while (count > 0) {
   136         int n = count;
   137         if (n > 128) {
   138             n = 128;
   139         }
   140         *dst++ = (uint8_t)(n - 1);
   141         *dst++ = (uint8_t)(value >> 8);
   142         *dst++ = (uint8_t)value;
   143         count -= n;
   144     }
   145     return dst;
   146 }
   148 static uint8_t* flush_same8(uint8_t dst[], uint8_t value, int count) {
   149     while (count > 0) {
   150         int n = count;
   151         if (n > 128) {
   152             n = 128;
   153         }
   154         *dst++ = (uint8_t)(n - 1);
   155         *dst++ = (uint8_t)value;
   156         count -= n;
   157     }
   158     return dst;
   159 }
   161 static uint8_t* flush_diff16(uint8_t* SK_RESTRICT dst,
   162                              const uint16_t* SK_RESTRICT src, int count) {
   163     while (count > 0) {
   164         int n = count;
   165         if (n > 128) {
   166             n = 128;
   167         }
   168         *dst++ = (uint8_t)(n + 127);
   169         PB_MEMCPY(dst, src, n * sizeof(uint16_t));
   170         src += n;
   171         dst += n * sizeof(uint16_t);
   172         count -= n;
   173     }
   174     return dst;
   175 }
   177 static uint8_t* flush_diff8(uint8_t* SK_RESTRICT dst,
   178                             const uint8_t* SK_RESTRICT src, int count) {
   179     while (count > 0) {
   180         int n = count;
   181         if (n > 128) {
   182             n = 128;
   183         }
   184         *dst++ = (uint8_t)(n + 127);
   185         PB_MEMCPY(dst, src, n);
   186         src += n;
   187         dst += n;
   188         count -= n;
   189     }
   190     return dst;
   191 }
   193 size_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count,
   194                           uint8_t* SK_RESTRICT dst) {
   195     uint8_t* origDst = dst;
   196     const uint16_t* stop = src + count;
   198     for (;;) {
   199         count = stop - src;
   200         SkASSERT(count >= 0);
   201         if (count == 0) {
   202             return dst - origDst;
   203         }
   204         if (1 == count) {
   205             *dst++ = 0;
   206             *dst++ = (uint8_t)(*src >> 8);
   207             *dst++ = (uint8_t)*src;
   208             return dst - origDst;
   209         }
   211         unsigned value = *src;
   212         const uint16_t* s = src + 1;
   214         if (*s == value) { // accumulate same values...
   215             do {
   216                 s++;
   217                 if (s == stop) {
   218                     break;
   219                 }
   220             } while (*s == value);
   221             dst = flush_same16(dst, value, s - src);
   222         } else {    // accumulate diff values...
   223             do {
   224                 if (++s == stop) {
   225                     goto FLUSH_DIFF;
   226                 }
   227             } while (*s != s[-1]);
   228             s -= 1; // back up so we don't grab one of the "same" values that follow
   229         FLUSH_DIFF:
   230             dst = flush_diff16(dst, src, s - src);
   231         }
   232         src = s;
   233     }
   234 }
   236 size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count,
   237                          uint8_t* SK_RESTRICT dst) {
   238     uint8_t* origDst = dst;
   239     const uint8_t* stop = src + count;
   241     for (;;) {
   242         count = stop - src;
   243         SkASSERT(count >= 0);
   244         if (count == 0) {
   245             return dst - origDst;
   246         }
   247         if (1 == count) {
   248             *dst++ = 0;
   249             *dst++ = *src;
   250             return dst - origDst;
   251         }
   253         unsigned value = *src;
   254         const uint8_t* s = src + 1;
   256         if (*s == value) { // accumulate same values...
   257             do {
   258                 s++;
   259                 if (s == stop) {
   260                     break;
   261                 }
   262             } while (*s == value);
   263             dst = flush_same8(dst, value, s - src);
   264         } else {    // accumulate diff values...
   265             do {
   266                 if (++s == stop) {
   267                     goto FLUSH_DIFF;
   268                 }
   269                 // only stop if we hit 3 in a row,
   270                 // otherwise we get bigger than compuatemax
   271             } while (*s != s[-1] || s[-1] != s[-2]);
   272             s -= 2; // back up so we don't grab the "same" values that follow
   273         FLUSH_DIFF:
   274             dst = flush_diff8(dst, src, s - src);
   275         }
   276         src = s;
   277     }
   278 }
   280 #include "SkUtils.h"
   282 int SkPackBits::Unpack16(const uint8_t* SK_RESTRICT src, size_t srcSize,
   283                          uint16_t* SK_RESTRICT dst) {
   284     uint16_t* origDst = dst;
   285     const uint8_t* stop = src + srcSize;
   287     while (src < stop) {
   288         unsigned n = *src++;
   289         if (n <= 127) {   // repeat count (n + 1)
   290             n += 1;
   291             sk_memset16(dst, (src[0] << 8) | src[1], n);
   292             src += 2;
   293         } else {    // same count (n - 127)
   294             n -= 127;
   295             PB_MEMCPY(dst, src, n * sizeof(uint16_t));
   296             src += n * sizeof(uint16_t);
   297         }
   298         dst += n;
   299     }
   300     SkASSERT(src == stop);
   301     return dst - origDst;
   302 }
   304 int SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
   305                         uint8_t* SK_RESTRICT dst) {
   306     uint8_t* origDst = dst;
   307     const uint8_t* stop = src + srcSize;
   309     while (src < stop) {
   310         unsigned n = *src++;
   311         if (n <= 127) {   // repeat count (n + 1)
   312             n += 1;
   313             PB_MEMSET(dst, *src++, n);
   314         } else {    // same count (n - 127)
   315             n -= 127;
   316             PB_MEMCPY(dst, src, n);
   317             src += n;
   318         }
   319         dst += n;
   320     }
   321     SkASSERT(src == stop);
   322     return dst - origDst;
   323 }
   325 enum UnpackState {
   326     CLEAN_STATE,
   327     REPEAT_BYTE_STATE,
   328     COPY_SRC_STATE
   329 };
   331 void SkPackBits::Unpack8(uint8_t* SK_RESTRICT dst, size_t dstSkip,
   332                          size_t dstWrite, const uint8_t* SK_RESTRICT src) {
   333     if (dstWrite == 0) {
   334         return;
   335     }
   337     UnpackState state = CLEAN_STATE;
   338     size_t      stateCount = 0;
   340     // state 1: do the skip-loop
   341     while (dstSkip > 0) {
   342         unsigned n = *src++;
   343         if (n <= 127) {   // repeat count (n + 1)
   344             n += 1;
   345             if (n > dstSkip) {
   346                 state = REPEAT_BYTE_STATE;
   347                 stateCount = n - dstSkip;
   348                 n = dstSkip;
   349                 // we don't increment src here, since its needed in stage 2
   350             } else {
   351                 src++;  // skip the src byte
   352             }
   353         } else {    // same count (n - 127)
   354             n -= 127;
   355             if (n > dstSkip) {
   356                 state = COPY_SRC_STATE;
   357                 stateCount = n - dstSkip;
   358                 n = dstSkip;
   359             }
   360             src += n;
   361         }
   362         dstSkip -= n;
   363     }
   365     // stage 2: perform any catchup from the skip-stage
   366     if (stateCount > dstWrite) {
   367         stateCount = dstWrite;
   368     }
   369     switch (state) {
   370         case REPEAT_BYTE_STATE:
   371             SkASSERT(stateCount > 0);
   372             register_memset_count(stateCount);
   373             PB_MEMSET(dst, *src++, stateCount);
   374             break;
   375         case COPY_SRC_STATE:
   376             SkASSERT(stateCount > 0);
   377             register_memcpy_count(stateCount);
   378             PB_MEMCPY(dst, src, stateCount);
   379             src += stateCount;
   380             break;
   381         default:
   382             SkASSERT(stateCount == 0);
   383             break;
   384     }
   385     dst += stateCount;
   386     dstWrite -= stateCount;
   388     // copy at most dstWrite bytes into dst[]
   389     while (dstWrite > 0) {
   390         unsigned n = *src++;
   391         if (n <= 127) {   // repeat count (n + 1)
   392             n += 1;
   393             if (n > dstWrite) {
   394                 n = dstWrite;
   395             }
   396             register_memset_count(n);
   397             PB_MEMSET(dst, *src++, n);
   398         } else {    // same count (n - 127)
   399             n -= 127;
   400             if (n > dstWrite) {
   401                 n = dstWrite;
   402             }
   403             register_memcpy_count(n);
   404             PB_MEMCPY(dst, src, n);
   405             src += n;
   406         }
   407         dst += n;
   408         dstWrite -= n;
   409     }
   410     SkASSERT(0 == dstWrite);
   411 }

mercurial