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 SkTDict_DEFINED
11#define SkTDict_DEFINED
12
13#include "SkChunkAlloc.h"
14#include "SkTSearch.h"
15#include "SkTDArray.h"
16
17template <typename T> class SkTDict : SkNoncopyable {
18public:
19    SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}
20
21    void reset()
22    {
23        fArray.reset();
24        fStrings.reset();
25    }
26
27    int count() const { return fArray.count(); }
28
29    bool set(const char name[], const T& value)
30    {
31        return set(name, strlen(name), value);
32    }
33
34    bool set(const char name[], size_t len, const T& value)
35    {
36        SkASSERT(name);
37
38        int index = this->find_index(name, len);
39
40        if (index >= 0)
41        {
42            fArray[index].fValue = value;
43            return false;
44        }
45        else
46        {
47            Pair*   pair = fArray.insert(~index);
48            char*   copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
49            memcpy(copy, name, len);
50            copy[len] = '\0';
51            pair->fName = copy;
52            pair->fValue = value;
53            return true;
54        }
55    }
56
57    bool find(const char name[]) const
58    {
59        return this->find_index(name) >= 0;
60    }
61
62    bool find(const char name[], size_t len) const
63    {
64        return this->find_index(name, len) >= 0;
65    }
66
67    bool find(const char name[], T* value) const
68    {
69        return find(name, strlen(name), value);
70    }
71
72    bool find(const char name[], size_t len, T* value) const
73    {
74        int index = this->find_index(name, len);
75
76        if (index >= 0)
77        {
78            if (value)
79                *value = fArray[index].fValue;
80            return true;
81        }
82        return false;
83    }
84
85    bool findKey(T& value, const char** name) const
86    {
87        const Pair* end = fArray.end();
88        for (const Pair* pair = fArray.begin(); pair < end; pair++) {
89            if (pair->fValue != value)
90                continue;
91            *name = pair->fName;
92            return true;
93        }
94        return false;
95    }
96
97public:
98    struct Pair {
99        const char* fName;
100        T           fValue;
101
102        friend int operator<(const Pair& a, const Pair& b)
103        {
104            return strcmp(a.fName, b.fName);
105        }
106        friend int operator!=(const Pair& a, const Pair& b)
107        {
108            return strcmp(a.fName, b.fName);
109        }
110    };
111    friend class Iter;
112
113public:
114    class Iter {
115    public:
116        Iter(const SkTDict<T>& dict)
117        {
118            fIter = dict.fArray.begin();
119            fStop = dict.fArray.end();
120        }
121        const char* next(T* value)
122        {
123            const char* name = NULL;
124            if (fIter < fStop)
125            {
126                name = fIter->fName;
127                if (value)
128                    *value = fIter->fValue;
129                fIter += 1;
130            }
131            return name;
132        }
133    private:
134        const Pair*   fIter;
135        const Pair*   fStop;
136    };
137
138private:
139    SkTDArray<Pair> fArray;
140    SkChunkAlloc    fStrings;
141
142    int find_index(const char name[]) const
143    {
144        return find_index(name, strlen(name));
145    }
146
147    int find_index(const char name[], size_t len) const
148    {
149        SkASSERT(name);
150
151        int count = fArray.count();
152        int index = ~0;
153
154        if (count)
155            index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
156        return index;
157    }
158    friend class Iter;
159};
160
161#endif
162