aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkMetaData.h117
-rw-r--r--src/core/SkMetaData.cpp217
-rw-r--r--tests/MetaDataTest.cpp112
-rw-r--r--tests/tests_files.mk1
4 files changed, 248 insertions, 199 deletions
diff --git a/include/core/SkMetaData.h b/include/core/SkMetaData.h
index 95097107f2..5e6f376f45 100644
--- a/include/core/SkMetaData.h
+++ b/include/core/SkMetaData.h
@@ -19,47 +19,69 @@
#include "SkScalar.h"
+class SkRefCnt;
+
class SkMetaData {
public:
+ /**
+ * Used to manage the life-cycle of a ptr in the metadata. This is option
+ * in setPtr, and is only invoked when either copying one metadata to
+ * another, or when the metadata is destroyed.
+ *
+ * setPtr(name, ptr, proc) {
+ * fPtr = proc(ptr, true);
+ * }
+ *
+ * copy: A = B {
+ * A.fPtr = B.fProc(B.fPtr, true);
+ * }
+ *
+ * ~SkMetaData {
+ * fProc(fPtr, false);
+ * }
+ */
+ typedef void* (*PtrProc)(void* ptr, bool doRef);
+
+ /**
+ * Implements PtrProc for SkRefCnt pointers
+ */
+ static void* RefCntProc(void* ptr, bool doRef);
+
SkMetaData();
SkMetaData(const SkMetaData& src);
~SkMetaData();
SkMetaData& operator=(const SkMetaData& src);
- void reset();
+ void reset();
- bool findS32(const char name[], int32_t* value = NULL) const;
- bool findScalar(const char name[], SkScalar* value = NULL) const;
- const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const;
+ bool findS32(const char name[], int32_t* value = NULL) const;
+ bool findScalar(const char name[], SkScalar* value = NULL) const;
+ const SkScalar* findScalars(const char name[], int* count,
+ SkScalar values[] = NULL) const;
const char* findString(const char name[]) const;
- bool findPtr(const char name[], void** value = NULL) const;
- bool findBool(const char name[], bool* value = NULL) const;
+ bool findPtr(const char name[], void** value = NULL, PtrProc* = NULL) const;
+ bool findBool(const char name[], bool* value = NULL) const;
const void* findData(const char name[], size_t* byteCount = NULL) const;
- bool hasS32(const char name[], int32_t value) const
- {
+ bool hasS32(const char name[], int32_t value) const {
int32_t v;
return this->findS32(name, &v) && v == value;
}
- bool hasScalar(const char name[], SkScalar value) const
- {
- SkScalar v;
+ bool hasScalar(const char name[], SkScalar value) const {
+ SkScalar v;
return this->findScalar(name, &v) && v == value;
}
- bool hasString(const char name[], const char value[]) const
- {
+ bool hasString(const char name[], const char value[]) const {
const char* v = this->findString(name);
return v == NULL && value == NULL ||
v != NULL && value != NULL && !strcmp(v, value);
}
- bool hasPtr(const char name[], void* value) const
- {
- void* v;
+ bool hasPtr(const char name[], void* value) const {
+ void* v;
return this->findPtr(name, &v) && v == value;
}
- bool hasBool(const char name[], bool value) const
- {
+ bool hasBool(const char name[], bool value) const {
bool v;
return this->findBool(name, &v) && v == value;
}
@@ -69,23 +91,35 @@ public:
return NULL != ptr && len == byteCount && !memcmp(ptr, data, len);
}
- void setS32(const char name[], int32_t value);
- void setScalar(const char name[], SkScalar value);
+ void setS32(const char name[], int32_t value);
+ void setScalar(const char name[], SkScalar value);
SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL);
- void setString(const char name[], const char value[]);
- void setPtr(const char name[], void* value);
- void setBool(const char name[], bool value);
+ void setString(const char name[], const char value[]);
+ void setPtr(const char name[], void* value, PtrProc proc = NULL);
+ void setBool(const char name[], bool value);
// the data is copied from the input pointer.
- void setData(const char name[], const void* data, size_t byteCount);
-
- bool removeS32(const char name[]);
- bool removeScalar(const char name[]);
- bool removeString(const char name[]);
- bool removePtr(const char name[]);
- bool removeBool(const char name[]);
- bool removeData(const char name[]);
-
- SkDEBUGCODE(static void UnitTest();)
+ void setData(const char name[], const void* data, size_t byteCount);
+
+ bool removeS32(const char name[]);
+ bool removeScalar(const char name[]);
+ bool removeString(const char name[]);
+ bool removePtr(const char name[]);
+ bool removeBool(const char name[]);
+ bool removeData(const char name[]);
+
+ // helpers for SkRefCnt
+ bool findRefCnt(const char name[], SkRefCnt** ptr = NULL) {
+ return this->findPtr(name, reinterpret_cast<void**>(ptr));
+ }
+ bool hasRefCnt(const char name[], SkRefCnt* ptr) {
+ return this->hasPtr(name, ptr);
+ }
+ void setRefCnt(const char name[], SkRefCnt* ptr) {
+ this->setPtr(name, ptr, RefCntProc);
+ }
+ bool removeRefCnt(const char name[]) {
+ return this->removePtr(name);
+ }
enum Type {
kS32_Type,
@@ -110,7 +144,7 @@ public:
/** Reset the iterator, so that calling next() will return the first
data element. This is done implicitly in the constructor.
*/
- void reset(const SkMetaData&);
+ void reset(const SkMetaData&);
/** Each time next is called, it returns the name of the next data element,
or null when there are no more elements. If non-null is returned, then the
@@ -128,22 +162,7 @@ public:
Rec* fNext;
uint16_t fDataCount; // number of elements
uint8_t fDataLen; // sizeof a single element
-#ifdef SK_DEBUG
- Type fType;
-#else
uint8_t fType;
-#endif
-
-#ifdef SK_DEBUG
- const char* fName;
- union {
- int32_t fS32;
- SkScalar fScalar;
- const char* fString;
- void* fPtr;
- bool fBool;
- } fData;
-#endif
const void* data() const { return (this + 1); }
void* data() { return (this + 1); }
diff --git a/src/core/SkMetaData.cpp b/src/core/SkMetaData.cpp
index c871efb136..b1901dc6db 100644
--- a/src/core/SkMetaData.cpp
+++ b/src/core/SkMetaData.cpp
@@ -16,6 +16,24 @@
*/
#include "SkMetaData.h"
+#include "SkRefCnt.h"
+
+struct PtrPair {
+ void* fPtr;
+ SkMetaData::PtrProc fProc;
+};
+
+void* SkMetaData::RefCntProc(void* ptr, bool doRef) {
+ SkASSERT(ptr);
+ SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr);
+
+ if (doRef) {
+ refcnt->ref();
+ } else {
+ refcnt->unref();
+ }
+ return ptr;
+}
SkMetaData::SkMetaData() : fRec(NULL)
{
@@ -34,8 +52,13 @@ SkMetaData::~SkMetaData()
void SkMetaData::reset()
{
Rec* rec = fRec;
- while (rec)
- {
+ while (rec) {
+ if (kPtr_Type == rec->fType) {
+ PtrPair* pair = (PtrPair*)rec->data();
+ if (pair->fProc && pair->fPtr) {
+ pair->fPtr = pair->fProc(pair->fPtr, false);
+ }
+ }
Rec* next = rec->fNext;
Rec::Free(rec);
rec = next;
@@ -79,9 +102,9 @@ void SkMetaData::setString(const char name[], const char value[])
(void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
}
-void SkMetaData::setPtr(const char name[], void* ptr)
-{
- (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
+void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
+ PtrPair pair = { ptr, proc };
+ (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1);
}
void SkMetaData::setBool(const char name[], bool value)
@@ -115,32 +138,12 @@ void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type
memcpy(rec->data(), data, dataSize * count);
memcpy(rec->name(), name, len + 1);
-#ifdef SK_DEBUG
- rec->fName = rec->name();
- switch (type) {
- case kS32_Type:
- rec->fData.fS32 = *(const int32_t*)rec->data();
- break;
- case kScalar_Type:
- rec->fData.fScalar = *(const SkScalar*)rec->data();
- break;
- case kString_Type:
- rec->fData.fString = (const char*)rec->data();
- break;
- case kPtr_Type:
- rec->fData.fPtr = *(void**)rec->data();
- break;
- case kBool_Type:
- rec->fData.fBool = *(const bool*)rec->data();
- break;
- case kData_Type:
- rec->fData.fPtr = rec->data();
- break;
- default:
- SkASSERT(!"bad type");
- break;
+ if (kPtr_Type == type) {
+ PtrPair* pair = (PtrPair*)rec->data();
+ if (pair->fProc && pair->fPtr) {
+ pair->fPtr = pair->fProc(pair->fPtr, true);
+ }
}
-#endif
rec->fNext = fRec;
fRec = rec;
@@ -187,14 +190,17 @@ const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar
return NULL;
}
-bool SkMetaData::findPtr(const char name[], void** value) const
-{
+bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
const Rec* rec = this->find(name, kPtr_Type);
- if (rec)
- {
+ if (rec) {
SkASSERT(rec->fDataCount == 1);
- if (value)
- *value = *(void**)rec->data();
+ const PtrPair* pair = (const PtrPair*)rec->data();
+ if (ptr) {
+ *ptr = pair->fPtr;
+ }
+ if (proc) {
+ *proc = pair->fProc;
+ }
return true;
}
return false;
@@ -244,19 +250,24 @@ const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
return NULL;
}
-bool SkMetaData::remove(const char name[], Type type)
-{
+bool SkMetaData::remove(const char name[], Type type) {
Rec* rec = fRec;
Rec* prev = NULL;
- while (rec)
- {
+ while (rec) {
Rec* next = rec->fNext;
- if (rec->fType == type && !strcmp(rec->name(), name))
- {
- if (prev)
+ if (rec->fType == type && !strcmp(rec->name(), name)) {
+ if (prev) {
prev->fNext = next;
- else
+ } else {
fRec = next;
+ }
+
+ if (kPtr_Type == type) {
+ PtrPair* pair = (PtrPair*)rec->data();
+ if (pair->fProc && pair->fPtr) {
+ (void)pair->fProc(pair->fPtr, false);
+ }
+ }
Rec::Free(rec);
return true;
}
@@ -295,28 +306,26 @@ bool SkMetaData::removeData(const char name[]) {
return this->remove(name, kData_Type);
}
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-SkMetaData::Iter::Iter(const SkMetaData& metadata)
-{
+SkMetaData::Iter::Iter(const SkMetaData& metadata) {
fRec = metadata.fRec;
}
-void SkMetaData::Iter::reset(const SkMetaData& metadata)
-{
+void SkMetaData::Iter::reset(const SkMetaData& metadata) {
fRec = metadata.fRec;
}
-const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count)
-{
+const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
const char* name = NULL;
- if (fRec)
- {
- if (t)
+ if (fRec) {
+ if (t) {
*t = (SkMetaData::Type)fRec->fType;
- if (count)
+ }
+ if (count) {
*count = fRec->fDataCount;
+ }
name = fRec->name();
fRec = fRec->fNext;
@@ -324,105 +333,13 @@ const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count)
return name;
}
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size)
-{
+SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
return (Rec*)sk_malloc_throw(size);
}
-void SkMetaData::Rec::Free(Rec* rec)
-{
+void SkMetaData::Rec::Free(Rec* rec) {
sk_free(rec);
}
-///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
-
-void SkMetaData::UnitTest()
-{
-#ifdef SK_SUPPORT_UNITTEST
- SkMetaData m1;
-
- SkASSERT(!m1.findS32("int"));
- SkASSERT(!m1.findScalar("scalar"));
- SkASSERT(!m1.findString("hello"));
- SkASSERT(!m1.removeS32("int"));
- SkASSERT(!m1.removeScalar("scalar"));
- SkASSERT(!m1.removeString("hello"));
- SkASSERT(!m1.removeString("true"));
- SkASSERT(!m1.removeString("false"));
-
- m1.setS32("int", 12345);
- m1.setScalar("scalar", SK_Scalar1 * 42);
- m1.setString("hello", "world");
- m1.setPtr("ptr", &m1);
- m1.setBool("true", true);
- m1.setBool("false", false);
-
- int32_t n;
- SkScalar s;
-
- m1.setScalar("scalar", SK_Scalar1/2);
-
- SkASSERT(m1.findS32("int", &n) && n == 12345);
- SkASSERT(m1.findScalar("scalar", &s) && s == SK_Scalar1/2);
- SkASSERT(!strcmp(m1.findString("hello"), "world"));
- SkASSERT(m1.hasBool("true", true));
- SkASSERT(m1.hasBool("false", false));
-
- Iter iter(m1);
- const char* name;
-
- static const struct {
- const char* fName;
- SkMetaData::Type fType;
- int fCount;
- } gElems[] = {
- { "int", SkMetaData::kS32_Type, 1 },
- { "scalar", SkMetaData::kScalar_Type, 1 },
- { "ptr", SkMetaData::kPtr_Type, 1 },
- { "hello", SkMetaData::kString_Type, sizeof("world") },
- { "true", SkMetaData::kBool_Type, 1 },
- { "false", SkMetaData::kBool_Type, 1 }
- };
-
- int loop = 0;
- int count;
- SkMetaData::Type t;
- while ((name = iter.next(&t, &count)) != NULL)
- {
- int match = 0;
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++)
- {
- if (!strcmp(name, gElems[i].fName))
- {
- match += 1;
- SkASSERT(gElems[i].fType == t);
- SkASSERT(gElems[i].fCount == count);
- }
- }
- SkASSERT(match == 1);
- loop += 1;
- }
- SkASSERT(loop == SK_ARRAY_COUNT(gElems));
-
- SkASSERT(m1.removeS32("int"));
- SkASSERT(m1.removeScalar("scalar"));
- SkASSERT(m1.removeString("hello"));
- SkASSERT(m1.removeBool("true"));
- SkASSERT(m1.removeBool("false"));
-
- SkASSERT(!m1.findS32("int"));
- SkASSERT(!m1.findScalar("scalar"));
- SkASSERT(!m1.findString("hello"));
- SkASSERT(!m1.findBool("true"));
- SkASSERT(!m1.findBool("false"));
-#endif
-}
-
-#endif
-
-
diff --git a/tests/MetaDataTest.cpp b/tests/MetaDataTest.cpp
new file mode 100644
index 0000000000..70829d49d7
--- /dev/null
+++ b/tests/MetaDataTest.cpp
@@ -0,0 +1,112 @@
+#include "Test.h"
+#include "SkMetaData.h"
+
+static void test_ptrs(skiatest::Reporter* reporter) {
+ SkRefCnt ref;
+ REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
+
+ {
+ SkMetaData md0, md1;
+ const char name[] = "refcnt";
+
+ md0.setRefCnt(name, &ref);
+ REPORTER_ASSERT(reporter, md0.findRefCnt(name));
+ REPORTER_ASSERT(reporter, md0.hasRefCnt(name, &ref));
+ REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
+
+ md1 = md0;
+ REPORTER_ASSERT(reporter, md1.findRefCnt(name));
+ REPORTER_ASSERT(reporter, md1.hasRefCnt(name, &ref));
+ REPORTER_ASSERT(reporter, 3 == ref.getRefCnt());
+
+ REPORTER_ASSERT(reporter, md0.removeRefCnt(name));
+ REPORTER_ASSERT(reporter, !md0.findRefCnt(name));
+ REPORTER_ASSERT(reporter, !md0.hasRefCnt(name, &ref));
+ REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
+ }
+ REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
+}
+
+static void TestMetaData(skiatest::Reporter* reporter) {
+ SkMetaData m1;
+
+ REPORTER_ASSERT(reporter, !m1.findS32("int"));
+ REPORTER_ASSERT(reporter, !m1.findScalar("scalar"));
+ REPORTER_ASSERT(reporter, !m1.findString("hello"));
+ REPORTER_ASSERT(reporter, !m1.removeS32("int"));
+ REPORTER_ASSERT(reporter, !m1.removeScalar("scalar"));
+ REPORTER_ASSERT(reporter, !m1.removeString("hello"));
+ REPORTER_ASSERT(reporter, !m1.removeString("true"));
+ REPORTER_ASSERT(reporter, !m1.removeString("false"));
+
+ m1.setS32("int", 12345);
+ m1.setScalar("scalar", SK_Scalar1 * 42);
+ m1.setString("hello", "world");
+ m1.setPtr("ptr", &m1);
+ m1.setBool("true", true);
+ m1.setBool("false", false);
+
+ int32_t n;
+ SkScalar s;
+
+ m1.setScalar("scalar", SK_Scalar1/2);
+
+ REPORTER_ASSERT(reporter, m1.findS32("int", &n) && n == 12345);
+ REPORTER_ASSERT(reporter, m1.findScalar("scalar", &s) && s == SK_Scalar1/2);
+ REPORTER_ASSERT(reporter, !strcmp(m1.findString("hello"), "world"));
+ REPORTER_ASSERT(reporter, m1.hasBool("true", true));
+ REPORTER_ASSERT(reporter, m1.hasBool("false", false));
+
+ SkMetaData::Iter iter(m1);
+ const char* name;
+
+ static const struct {
+ const char* fName;
+ SkMetaData::Type fType;
+ int fCount;
+ } gElems[] = {
+ { "int", SkMetaData::kS32_Type, 1 },
+ { "scalar", SkMetaData::kScalar_Type, 1 },
+ { "ptr", SkMetaData::kPtr_Type, 1 },
+ { "hello", SkMetaData::kString_Type, sizeof("world") },
+ { "true", SkMetaData::kBool_Type, 1 },
+ { "false", SkMetaData::kBool_Type, 1 }
+ };
+
+ int loop = 0;
+ int count;
+ SkMetaData::Type t;
+ while ((name = iter.next(&t, &count)) != NULL)
+ {
+ int match = 0;
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++)
+ {
+ if (!strcmp(name, gElems[i].fName))
+ {
+ match += 1;
+ REPORTER_ASSERT(reporter, gElems[i].fType == t);
+ REPORTER_ASSERT(reporter, gElems[i].fCount == count);
+ }
+ }
+ REPORTER_ASSERT(reporter, match == 1);
+ loop += 1;
+ }
+ REPORTER_ASSERT(reporter, loop == SK_ARRAY_COUNT(gElems));
+
+ REPORTER_ASSERT(reporter, m1.removeS32("int"));
+ REPORTER_ASSERT(reporter, m1.removeScalar("scalar"));
+ REPORTER_ASSERT(reporter, m1.removeString("hello"));
+ REPORTER_ASSERT(reporter, m1.removeBool("true"));
+ REPORTER_ASSERT(reporter, m1.removeBool("false"));
+
+ REPORTER_ASSERT(reporter, !m1.findS32("int"));
+ REPORTER_ASSERT(reporter, !m1.findScalar("scalar"));
+ REPORTER_ASSERT(reporter, !m1.findString("hello"));
+ REPORTER_ASSERT(reporter, !m1.findBool("true"));
+ REPORTER_ASSERT(reporter, !m1.findBool("false"));
+
+ test_ptrs(reporter);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("MetaData", TestMetaDataClass, TestMetaData)
diff --git a/tests/tests_files.mk b/tests/tests_files.mk
index cee5cfe97e..9f8d6dff82 100644
--- a/tests/tests_files.mk
+++ b/tests/tests_files.mk
@@ -13,6 +13,7 @@ SOURCE := \
InfRectTest.cpp \
MathTest.cpp \
MatrixTest.cpp \
+ MetaDataTest.cpp \
PackBitsTest.cpp \
PaintTest.cpp \
ParsePathTest.cpp \