OLD | NEW |
| (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 } | |
OLD | NEW |