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.

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

mercurial