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
15class SkRefCnt;
16
17class SK_API SkMetaData {
18public:
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
60    bool hasS32(const char name[], int32_t value) const {
61        int32_t v;
62        return this->findS32(name, &v) && v == value;
63    }
64    bool hasScalar(const char name[], SkScalar value) const {
65        SkScalar v;
66        return this->findScalar(name, &v) && v == value;
67    }
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    }
73    bool hasPtr(const char name[], void* value) const {
74        void* v;
75        return this->findPtr(name, &v) && v == value;
76    }
77    bool hasBool(const char name[], bool value) const {
78        bool    v;
79        return this->findBool(name, &v) && v == value;
80    }
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 NULL != 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    }
107    bool hasRefCnt(const char name[], SkRefCnt* ptr) {
108        return this->hasPtr(name, ptr);
109    }
110    void setRefCnt(const char name[], SkRefCnt* ptr) {
111        this->setPtr(name, ptr, RefCntProc);
112    }
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:
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
153public:
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
160        const void* data() const { return (this + 1); }
161        void*       data() { return (this + 1); }
162        const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
163        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