1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef SkMetaData_DEFINED
11 #define SkMetaData_DEFINED
12 
13 #include "SkScalar.h"
14 
15 class SkRefCnt;
16 
17 class SK_API SkMetaData {
18 public:
19     /**
20      *  Used to manage the life-cycle of a ptr in the metadata. This is option
21      *  in setPtr, and is only invoked when either copying one metadata to
22      *  another, or when the metadata is destroyed.
23      *
24      *  setPtr(name, ptr, proc) {
25      *      fPtr = proc(ptr, true);
26      *  }
27      *
28      *  copy: A = B {
29      *      A.fPtr = B.fProc(B.fPtr, true);
30      *  }
31      *
32      *  ~SkMetaData {
33      *      fProc(fPtr, false);
34      *  }
35      */
36     typedef void* (*PtrProc)(void* ptr, bool doRef);
37 
38     /**
39      *  Implements PtrProc for SkRefCnt pointers
40      */
41     static void* RefCntProc(void* ptr, bool doRef);
42 
43     SkMetaData();
44     SkMetaData(const SkMetaData& src);
45     ~SkMetaData();
46 
47     SkMetaData& operator=(const SkMetaData& src);
48 
49     void reset();
50 
51     bool findS32(const char name[], int32_t* value = NULL) const;
52     bool findScalar(const char name[], SkScalar* value = NULL) const;
53     const SkScalar* findScalars(const char name[], int* count,
54                                 SkScalar values[] = NULL) const;
55     const char* findString(const char name[]) const;
56     bool findPtr(const char name[], void** value = NULL, PtrProc* = NULL) const;
57     bool findBool(const char name[], bool* value = NULL) const;
58     const void* findData(const char name[], size_t* byteCount = NULL) const;
59 
hasS32(const char name[],int32_t value)60     bool hasS32(const char name[], int32_t value) const {
61         int32_t v;
62         return this->findS32(name, &v) && v == value;
63     }
hasScalar(const char name[],SkScalar value)64     bool hasScalar(const char name[], SkScalar value) const {
65         SkScalar v;
66         return this->findScalar(name, &v) && v == value;
67     }
hasString(const char name[],const char value[])68     bool hasString(const char name[], const char value[]) const {
69         const char* v = this->findString(name);
70         return  (v == NULL && value == NULL) ||
71                 (v != NULL && value != NULL && !strcmp(v, value));
72     }
hasPtr(const char name[],void * value)73     bool hasPtr(const char name[], void* value) const {
74         void* v;
75         return this->findPtr(name, &v) && v == value;
76     }
hasBool(const char name[],bool value)77     bool hasBool(const char name[], bool value) const {
78         bool    v;
79         return this->findBool(name, &v) && v == value;
80     }
hasData(const char name[],const void * data,size_t byteCount)81     bool hasData(const char name[], const void* data, size_t byteCount) const {
82         size_t len;
83         const void* ptr = this->findData(name, &len);
84         return ptr && len == byteCount && !memcmp(ptr, data, len);
85     }
86 
87     void setS32(const char name[], int32_t value);
88     void setScalar(const char name[], SkScalar value);
89     SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL);
90     void setString(const char name[], const char value[]);
91     void setPtr(const char name[], void* value, PtrProc proc = NULL);
92     void setBool(const char name[], bool value);
93     // the data is copied from the input pointer.
94     void setData(const char name[], const void* data, size_t byteCount);
95 
96     bool removeS32(const char name[]);
97     bool removeScalar(const char name[]);
98     bool removeString(const char name[]);
99     bool removePtr(const char name[]);
100     bool removeBool(const char name[]);
101     bool removeData(const char name[]);
102 
103     // helpers for SkRefCnt
104     bool findRefCnt(const char name[], SkRefCnt** ptr = NULL) {
105         return this->findPtr(name, reinterpret_cast<void**>(ptr));
106     }
hasRefCnt(const char name[],SkRefCnt * ptr)107     bool hasRefCnt(const char name[], SkRefCnt* ptr) {
108         return this->hasPtr(name, ptr);
109     }
setRefCnt(const char name[],SkRefCnt * ptr)110     void setRefCnt(const char name[], SkRefCnt* ptr) {
111         this->setPtr(name, ptr, RefCntProc);
112     }
removeRefCnt(const char name[])113     bool removeRefCnt(const char name[]) {
114         return this->removePtr(name);
115     }
116 
117     enum Type {
118         kS32_Type,
119         kScalar_Type,
120         kString_Type,
121         kPtr_Type,
122         kBool_Type,
123         kData_Type,
124 
125         kTypeCount
126     };
127 
128     struct Rec;
129     class Iter;
130     friend class Iter;
131 
132     class Iter {
133     public:
Iter()134         Iter() : fRec(NULL) {}
135         Iter(const SkMetaData&);
136 
137         /** Reset the iterator, so that calling next() will return the first
138             data element. This is done implicitly in the constructor.
139         */
140         void reset(const SkMetaData&);
141 
142         /** Each time next is called, it returns the name of the next data element,
143             or null when there are no more elements. If non-null is returned, then the
144             element's type is returned (if not null), and the number of data values
145             is returned in count (if not null).
146         */
147         const char* next(Type*, int* count);
148 
149     private:
150         Rec* fRec;
151     };
152 
153 public:
154     struct Rec {
155         Rec*        fNext;
156         uint16_t    fDataCount; // number of elements
157         uint8_t     fDataLen;   // sizeof a single element
158         uint8_t     fType;
159 
dataRec160         const void* data() const { return (this + 1); }
dataRec161         void*       data() { return (this + 1); }
nameRec162         const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
nameRec163         char*       name() { return (char*)this->data() + fDataLen * fDataCount; }
164 
165         static Rec* Alloc(size_t);
166         static void Free(Rec*);
167     };
168     Rec*    fRec;
169 
170     const Rec* find(const char name[], Type) const;
171     void* set(const char name[], const void* data, size_t len, Type, int count);
172     bool remove(const char name[], Type);
173 };
174 
175 #endif
176