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 |