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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkMiniData.h ('k') | tests/MiniDataTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkMiniData.cpp
diff --git a/src/core/SkMiniData.cpp b/src/core/SkMiniData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ded62d1687a97220b83168b87be51372103f72d0
--- /dev/null
+++ b/src/core/SkMiniData.cpp
@@ -0,0 +1,80 @@
+#include "SkMiniData.h"
+
+namespace {
+
+// SkMiniData::fRep either stores a LongData* or is punned into a ShortData.
+// We use the low bits to distinguish the two: all pointers from malloc are at
+// least 8-byte aligned, leaving those low bits clear when it's a LongData*.
+
+static bool is_long(uint64_t rep) {
+ // Even on 32-bit machines, we require the bottom 3 bits from malloc'd pointers are clear.
+ // If any of those bottom 3 bits are set, it's from a ShortData's len. And if no bits are
+ // set anywhere, it's an empty SkMiniData, which also follows the ShortData path.
+ return rep && SkIsAlign8(rep);
+}
+
+// Can be used for any length, but we always use it for >=8.
+struct LongData {
+ size_t len;
+ uint8_t data[8]; // There are actually len >= 8 bytes here.
+
+ static uint64_t Create(const void* data, size_t len) {
+ SkASSERT(len > 7);
+ LongData* s = (LongData*)sk_malloc_throw(sizeof(size_t) + len);
+ s->len = len;
+ memcpy(s->data, data, len);
+
+ uint64_t rep = reinterpret_cast<uint64_t>(s);
+ SkASSERT(is_long(rep));
+ return rep;
+ }
+};
+
+// At most 7 bytes fit, but never mallocs.
+struct ShortData {
+ // Order matters here. len must align with the least signficant bits of a pointer.
+#ifdef SK_CPU_LENDIAN
+ uint8_t len;
+ uint8_t data[7];
+#else // Warning! Only the little-endian path has been tested.
+ uint8_t data[7];
+ uint8_t len;
+#endif
+
+ static uint64_t Create(const void* data, size_t len) {
+ SkASSERT(len <= 7);
+#ifdef SK_CPU_LENDIAN
+ ShortData s = { (uint8_t)len, {0, 0, 0, 0, 0, 0, 0} };
+#else // Warning! Only the little-endian path has been tested.
+ ShortData s = { {0, 0, 0, 0, 0, 0, 0}, (uint8_t)len };
+#endif
+ memcpy(s.data, data, len);
+ return *reinterpret_cast<uint64_t*>(&s);
+ }
+};
+
+} // namespace
+
+SkMiniData::SkMiniData(const void* data, size_t len)
+ : fRep(len <= 7 ? ShortData::Create(data, len)
+ : LongData::Create(data, len)) {}
+
+SkMiniData::SkMiniData(const SkMiniData& s)
+ : fRep(s.len() <= 7 ? ShortData::Create(s.data(), s.len())
+ : LongData::Create(s.data(), s.len())) {}
+
+SkMiniData::~SkMiniData() {
+ if (is_long(fRep)) {
+ sk_free(reinterpret_cast<void*>(fRep));
+ }
+}
+
+const void* SkMiniData::data() const {
+ return is_long(fRep) ? reinterpret_cast<const LongData*>( fRep)->data
+ : reinterpret_cast<const ShortData*>(&fRep)->data;
+}
+
+size_t SkMiniData::len() const {
+ return is_long(fRep) ? reinterpret_cast<const LongData*>( fRep)->len
+ : reinterpret_cast<const ShortData*>(&fRep)->len;
+}
« 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