Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/core/SkMiniData.cpp

Issue 573323002: Add SkMiniData. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: MSVC doesn't like uint8_t data[0]. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkMiniData.h ('k') | tests/MiniDataTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #include "SkMiniData.h"
2
3 namespace {
4
5 // SkMiniData::fRep either stores a LongData* or is punned into a ShortData.
6 // We use the low bits to distinguish the two: all pointers from malloc are at
7 // least 8-byte aligned, leaving those low bits clear when it's a LongData*.
8
9 static bool is_long(uint64_t rep) {
10 // Even on 32-bit machines, we require the bottom 3 bits from malloc'd point ers are clear.
11 // If any of those bottom 3 bits are set, it's from a ShortData's len. And if no bits are
12 // set anywhere, it's an empty SkMiniData, which also follows the ShortData path.
13 return rep && SkIsAlign8(rep);
14 }
15
16 // Can be used for any length, but we always use it for >=8.
17 struct LongData {
18 size_t len;
19 uint8_t data[8]; // There are actually len >= 8 bytes here.
20
21 static uint64_t Create(const void* data, size_t len) {
22 SkASSERT(len > 7);
23 LongData* s = (LongData*)sk_malloc_throw(sizeof(size_t) + len);
24 s->len = len;
25 memcpy(s->data, data, len);
26
27 uint64_t rep = reinterpret_cast<uint64_t>(s);
28 SkASSERT(is_long(rep));
29 return rep;
30 }
31 };
32
33 // At most 7 bytes fit, but never mallocs.
34 struct ShortData {
35 // Order matters here. len must align with the least signficant bits of a po inter.
36 #ifdef SK_CPU_LENDIAN
37 uint8_t len;
38 uint8_t data[7];
39 #else // Warning! Only the little-endian path has been tested.
40 uint8_t data[7];
41 uint8_t len;
42 #endif
43
44 static uint64_t Create(const void* data, size_t len) {
45 SkASSERT(len <= 7);
46 #ifdef SK_CPU_LENDIAN
47 ShortData s = { (uint8_t)len, {0, 0, 0, 0, 0, 0, 0} };
48 #else // Warning! Only the little-endian path has been tested.
49 ShortData s = { {0, 0, 0, 0, 0, 0, 0}, (uint8_t)len };
50 #endif
51 memcpy(s.data, data, len);
52 return *reinterpret_cast<uint64_t*>(&s);
53 }
54 };
55
56 } // namespace
57
58 SkMiniData::SkMiniData(const void* data, size_t len)
59 : fRep(len <= 7 ? ShortData::Create(data, len)
60 : LongData::Create(data, len)) {}
61
62 SkMiniData::SkMiniData(const SkMiniData& s)
63 : fRep(s.len() <= 7 ? ShortData::Create(s.data(), s.len())
64 : LongData::Create(s.data(), s.len())) {}
65
66 SkMiniData::~SkMiniData() {
67 if (is_long(fRep)) {
68 sk_free(reinterpret_cast<void*>(fRep));
69 }
70 }
71
72 const void* SkMiniData::data() const {
73 return is_long(fRep) ? reinterpret_cast<const LongData*>( fRep)->data
74 : reinterpret_cast<const ShortData*>(&fRep)->data;
75 }
76
77 size_t SkMiniData::len() const {
78 return is_long(fRep) ? reinterpret_cast<const LongData*>( fRep)->len
79 : reinterpret_cast<const ShortData*>(&fRep)->len;
80 }
OLDNEW
« no previous file with comments | « src/core/SkMiniData.h ('k') | tests/MiniDataTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698