11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkTDict_DEFINED
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkTDict_DEFINED
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkChunkAlloc.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTSearch.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTDArray.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttemplate <typename T> class SkTDict : SkNoncopyable {
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void reset()
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fArray.reset();
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fStrings.reset();
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count() const { return fArray.count(); }
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool set(const char name[], const T& value)
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return set(name, strlen(name), value);
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool set(const char name[], size_t len, const T& value)
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(name);
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int index = this->find_index(name, len);
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (index >= 0)
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fArray[index].fValue = value;
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Pair*   pair = fArray.insert(~index);
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            char*   copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(copy, name, len);
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            copy[len] = '\0';
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            pair->fName = copy;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            pair->fValue = value;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return true;
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool find(const char name[]) const
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->find_index(name) >= 0;
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool find(const char name[], size_t len) const
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->find_index(name, len) >= 0;
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool find(const char name[], T* value) const
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return find(name, strlen(name), value);
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool find(const char name[], size_t len, T* value) const
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int index = this->find_index(name, len);
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (index >= 0)
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (value)
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *value = fArray[index].fValue;
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return true;
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool findKey(T& value, const char** name) const
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Pair* end = fArray.end();
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (Pair* pair = fArray.begin(); pair < end; pair++) {
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (pair->fValue != value)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *name = pair->fName;
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return true;
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    struct Pair {
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* fName;
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        T           fValue;
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        friend int operator<(const Pair& a, const Pair& b)
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return strcmp(a.fName, b.fName);
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        friend int operator!=(const Pair& a, const Pair& b)
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return strcmp(a.fName, b.fName);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Iter;
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    class Iter {
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    public:
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Iter(const SkTDict<T>& dict)
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fIter = dict.fArray.begin();
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fStop = dict.fArray.end();
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* next(T* value)
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* name = NULL;
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fIter < fStop)
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                name = fIter->fName;
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value)
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *value = fIter->fValue;
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fIter += 1;
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return name;
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    private:
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Pair*   fIter;
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Pair*   fStop;
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTDArray<Pair> fArray;
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkChunkAlloc    fStrings;
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int find_index(const char name[]) const
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return find_index(name, strlen(name));
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int find_index(const char name[], size_t len) const
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(name);
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int count = fArray.count();
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int index = ~0;
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (count)
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return index;
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    friend class Iter;
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
163