text: /* include/graphics/SkTDict.h
  **
  ** Copyright 2006, Google Inc.
  **
  ** Licensed under the Apache License, Version 2.0 (the "License"); 
  ** you may not use this file except in compliance with the License. 
  ** You may obtain a copy of the License at 
  **
  **     http://www.apache.org/licenses/LICENSE-2.0 
  **
  ** Unless required by applicable law or agreed to in writing, software 
  ** distributed under the License is distributed on an "AS IS" BASIS, 
  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  ** See the License for the specific language governing permissions and 
  ** limitations under the License.
  */
  
  #ifndef SkTDict_DEFINED
  #define SkTDict_DEFINED
  
  #include "SkChunkAlloc.h"
  #include "SkTSearch.h"
  #include "SkTDArray.h"
  
  template <typename T> class SkTDict : SkNoncopyable {
  public:
      SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}
  
      void reset()
      {
          fArray.reset();
          fStrings.reset();
      }
  
      int count() const { return fArray.count(); }
  
      bool set(const char name[], const T& value)
      {
          return set(name, strlen(name), value);
      }
  
      bool set(const char name[], size_t len, const T& value)
      {
          SkASSERT(name);
  
          int index = this->find_index(name, len);
  
          if (index >= 0)
          {
              fArray[index].fValue = value;
              return false;
          }
          else
          {
              Pair*   pair = fArray.insert(~index);
              char*   copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
              memcpy(copy, name, len);
              copy[len] = '\0';
              pair->fName = copy;
              pair->fValue = value;
              return true;
          }
      }
  
      bool find(const char name[]) const
      {
          return this->find_index(name) >= 0;
      }
  
      bool find(const char name[], size_t len) const
      {
          return this->find_index(name, len) >= 0;
      }
  
      bool find(const char name[], T* value) const
      {
          return find(name, strlen(name), value);
      }
  
      bool find(const char name[], size_t len, T* value) const
      {
          int index = this->find_index(name, len);
  
          if (index >= 0)
          {
              if (value)
                  *value = fArray[index].fValue;
              return true;
          }
          return false;
      }
  
      bool findKey(T& value, const char** name) const
      {
          Pair* end = fArray.end();
          for (Pair* pair = fArray.begin(); pair < end; pair++) {
              if (pair->fValue != value)
                  continue;
              *name = pair->fName;
              return true;
          }
          return false;
      }
  
  public:
      struct Pair {
          const char* fName;
          T           fValue;
  
          friend int operator<(const Pair& a, const Pair& b)
          {
              return strcmp(a.fName, b.fName);
          }
          friend int operator!=(const Pair& a, const Pair& b)
          {
              return strcmp(a.fName, b.fName);
          }
      };
      friend class Iter;
  
  public:
      class Iter {
      public:
          Iter(const SkTDict<T>& dict)
          {
              fIter = dict.fArray.begin();
              fStop = dict.fArray.end();
          }
          const char* next(T* value)
          {
              const char* name = NULL;
              if (fIter < fStop)
              {
                  name = fIter->fName;
                  if (value)
                      *value = fIter->fValue;
                  fIter += 1;
              }
              return name;
          }
      private:
          Pair*   fIter;
          Pair*   fStop;
      };
  
  private:
      SkTDArray<Pair> fArray;
      SkChunkAlloc    fStrings;
  
      int find_index(const char name[]) const
      {
          return find_index(name, strlen(name));
      }
  
      int find_index(const char name[], size_t len) const
      {
          SkASSERT(name);
  
          int count = fArray.count();
          int index = ~0;
  
          if (count)
              index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
          return index;
      }
      friend class Iter;
  };
  
  #endif
  
  