aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkData.cpp
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-11 17:24:49 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-11 17:24:49 +0000
commit91bd45967c6ca1ec408a0fefd3de0dcf3d03294a (patch)
treeaf63be29f18d9206eb09f3a773bdee1800ab99c7 /src/core/SkData.cpp
parent22b13f3628ff3560319d32fca0891608dc80bd41 (diff)
add SkDataSet class, so SkAnnotation can be more immutable-like
Review URL: https://codereview.appspot.com/6354091 git-svn-id: http://skia.googlecode.com/svn/trunk@4542 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkData.cpp')
-rw-r--r--src/core/SkData.cpp120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp
index 496d599379..618ee35f07 100644
--- a/src/core/SkData.cpp
+++ b/src/core/SkData.cpp
@@ -122,3 +122,123 @@ SkData* SkData::NewWithCString(const char cstr[]) {
return NewWithCopy(cstr, size);
}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkDataSet.h"
+#include "SkStream.h"
+
+static SkData* dupdata(SkData* data) {
+ if (data) {
+ data->ref();
+ } else {
+ data = SkData::NewEmpty();
+ }
+ return data;
+}
+
+static SkData* findValue(const char key[], const SkDataSet::Pair array[], int n) {
+ for (int i = 0; i < n; ++i) {
+ if (!strcmp(key, array[i].fKey)) {
+ return array[i].fValue;
+ }
+ }
+ return NULL;
+}
+
+static SkDataSet::Pair* allocatePairStorage(int count, size_t storage) {
+ size_t size = count * sizeof(SkDataSet::Pair) + storage;
+ return (SkDataSet::Pair*)sk_malloc_throw(size);
+}
+
+SkDataSet::SkDataSet(const char key[], SkData* value) {
+ size_t keyLen = strlen(key);
+
+ fCount = 1;
+ fKeySize = keyLen + 1;
+ fPairs = allocatePairStorage(1, keyLen + 1);
+
+ fPairs[0].fKey = (char*)(fPairs + 1);
+ memcpy(const_cast<char*>(fPairs[0].fKey), key, keyLen + 1);
+
+ fPairs[0].fValue = dupdata(value);
+}
+
+SkDataSet::SkDataSet(const Pair array[], int count) {
+ if (count < 1) {
+ fCount = 0;
+ fKeySize = 0;
+ fPairs = NULL;
+ return;
+ }
+
+ int i;
+ size_t keySize = 0;
+ for (i = 0; i < count; ++i) {
+ keySize += strlen(array[i].fKey) + 1;
+ }
+
+ Pair* pairs = fPairs = allocatePairStorage(count, keySize);
+ char* keyStorage = (char*)(pairs + count);
+
+ keySize = 0; // reset this, so we can compute the size for unique keys
+ int uniqueCount = 0;
+ for (int i = 0; i < count; ++i) {
+ if (!findValue(array[i].fKey, pairs, uniqueCount)) {
+ size_t len = strlen(array[i].fKey);
+ memcpy(keyStorage, array[i].fKey, len + 1);
+ pairs[uniqueCount].fKey = keyStorage;
+ keyStorage += len + 1;
+ keySize += len + 1;
+
+ pairs[uniqueCount].fValue = dupdata(array[i].fValue);
+ uniqueCount += 1;
+ }
+ }
+ fCount = uniqueCount;
+ fKeySize = keySize;
+}
+
+SkDataSet::~SkDataSet() {
+ for (int i = 0; i < fCount; ++i) {
+ fPairs[i].fValue->unref();
+ }
+ sk_free(fPairs); // this also frees the key storage
+}
+
+SkData* SkDataSet::find(const char key[]) const {
+ return findValue(key, fPairs, fCount);
+}
+
+void SkDataSet::writeToStream(SkWStream* stream) const {
+ stream->write32(fCount);
+ if (fCount > 0) {
+ stream->write32(fKeySize);
+ // our first key points to all the key storage
+ stream->write(fPairs[0].fKey, fKeySize);
+ for (int i = 0; i < fCount; ++i) {
+ stream->writeData(fPairs[i].fValue);
+ }
+ }
+}
+
+SkDataSet::SkDataSet(SkStream* stream) {
+ fCount = stream->readU32();
+ if (fCount > 0) {
+ fKeySize = stream->readU32();
+ fPairs = allocatePairStorage(fCount, fKeySize);
+ char* keyStorage = (char*)(fPairs + fCount);
+
+ stream->read(keyStorage, fKeySize);
+
+ for (int i = 0; i < fCount; ++i) {
+ fPairs[i].fKey = keyStorage;
+ keyStorage += strlen(keyStorage) + 1;
+ fPairs[i].fValue = stream->readData();
+ }
+ } else {
+ fKeySize = 0;
+ fPairs = NULL;
+ }
+}
+