aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkMetaData.h
blob: a8ebaac2adbb8ba01200a9bb3600884d5ce2e55b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkMetaData_DEFINED
#define SkMetaData_DEFINED

#include "SkScalar.h"

class SkRefCnt;

class SK_API 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();

    bool findS32(const char name[], int32_t* value = nullptr) const;
    bool findScalar(const char name[], SkScalar* value = nullptr) const;
    const SkScalar* findScalars(const char name[], int* count,
                                SkScalar values[] = nullptr) const;
    const char* findString(const char name[]) const;
    bool findPtr(const char name[], void** value = nullptr, PtrProc* = nullptr) const;
    bool findBool(const char name[], bool* value = nullptr) const;
    const void* findData(const char name[], size_t* byteCount = nullptr) 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;
        return this->findScalar(name, &v) && v == value;
    }
    bool hasString(const char name[], const char value[]) const {
        const char* v = this->findString(name);
        return  (v == nullptr && value == nullptr) ||
                (v != nullptr && value != nullptr && !strcmp(v, value));
    }
    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    v;
        return this->findBool(name, &v) && v == value;
    }
    bool hasData(const char name[], const void* data, size_t byteCount) const {
        size_t len;
        const void* ptr = this->findData(name, &len);
        return ptr && len == byteCount && !memcmp(ptr, data, len);
    }

    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[] = nullptr);
    void setString(const char name[], const char value[]);
    void setPtr(const char name[], void* value, PtrProc proc = nullptr);
    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[]);

    // helpers for SkRefCnt
    bool findRefCnt(const char name[], SkRefCnt** ptr = nullptr) {
        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,
        kScalar_Type,
        kString_Type,
        kPtr_Type,
        kBool_Type,
        kData_Type,

        kTypeCount
    };

    struct Rec;
    class Iter;
    friend class Iter;

    class Iter {
    public:
        Iter() : fRec(nullptr) {}
        Iter(const SkMetaData&);

        /** Reset the iterator, so that calling next() will return the first
            data element. This is done implicitly in the constructor.
        */
        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
            element's type is returned (if not null), and the number of data values
            is returned in count (if not null).
        */
        const char* next(Type*, int* count);

    private:
        Rec* fRec;
    };

public:
    struct Rec {
        Rec*        fNext;
        uint16_t    fDataCount; // number of elements
        uint8_t     fDataLen;   // sizeof a single element
        uint8_t     fType;

        const void* data() const { return (this + 1); }
        void*       data() { return (this + 1); }
        const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
        char*       name() { return (char*)this->data() + fDataLen * fDataCount; }

        static Rec* Alloc(size_t);
        static void Free(Rec*);
    };
    Rec*    fRec;

    const Rec* find(const char name[], Type) const;
    void* set(const char name[], const void* data, size_t len, Type, int count);
    bool remove(const char name[], Type);
};

#endif