LCOV - code coverage report
Current view: top level - xpcom/ds - nsCheapSets.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 64 1.6 %
Date: 2017-07-14 16:53:18 Functions: 1 21 4.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef __nsCheapSets_h__
       8             : #define __nsCheapSets_h__
       9             : 
      10             : #include "nsTHashtable.h"
      11             : #include <stdint.h>
      12             : 
      13             : enum nsCheapSetOperator
      14             : {
      15             :   OpNext = 0,   // enumerator says continue
      16             :   OpRemove = 1, // enumerator says remove and continue
      17             : };
      18             : 
      19             : /**
      20             :  * A set that takes up minimal size when there are 0 or 1 entries in the set.
      21             :  * Use for cases where sizes of 0 and 1 are even slightly common.
      22             :  */
      23             : template<typename EntryType>
      24             : class nsCheapSet
      25             : {
      26             : public:
      27             :   typedef typename EntryType::KeyType KeyType;
      28             :   typedef nsCheapSetOperator (*Enumerator)(EntryType* aEntry, void* userArg);
      29             : 
      30          12 :   nsCheapSet() : mState(ZERO) {}
      31           0 :   ~nsCheapSet() { Clear(); }
      32             : 
      33             :   /**
      34             :    * Remove all entries.
      35             :    */
      36           0 :   void Clear()
      37             :   {
      38           0 :     switch (mState) {
      39             :       case ZERO:
      40           0 :         break;
      41             :       case ONE:
      42           0 :         GetSingleEntry()->~EntryType();
      43           0 :         break;
      44             :       case MANY:
      45           0 :         delete mUnion.table;
      46           0 :         break;
      47             :       default:
      48           0 :         NS_NOTREACHED("bogus state");
      49           0 :         break;
      50             :     }
      51           0 :     mState = ZERO;
      52           0 :   }
      53             : 
      54             :   void Put(const KeyType aVal);
      55             : 
      56             :   void Remove(const KeyType aVal);
      57             : 
      58           0 :   bool Contains(const KeyType aVal)
      59             :   {
      60           0 :     switch (mState) {
      61             :       case ZERO:
      62           0 :         return false;
      63             :       case ONE:
      64           0 :         return GetSingleEntry()->KeyEquals(EntryType::KeyToPointer(aVal));
      65             :       case MANY:
      66           0 :         return !!mUnion.table->GetEntry(aVal);
      67             :       default:
      68           0 :         NS_NOTREACHED("bogus state");
      69           0 :         return false;
      70             :     }
      71             :   }
      72             : 
      73           0 :   uint32_t EnumerateEntries(Enumerator aEnumFunc, void* aUserArg)
      74             :   {
      75           0 :     switch (mState) {
      76             :       case ZERO:
      77           0 :         return 0;
      78             :       case ONE:
      79           0 :         if (aEnumFunc(GetSingleEntry(), aUserArg) == OpRemove) {
      80           0 :           GetSingleEntry()->~EntryType();
      81           0 :           mState = ZERO;
      82             :         }
      83           0 :         return 1;
      84             :       case MANY: {
      85           0 :         uint32_t n = mUnion.table->Count();
      86           0 :         for (auto iter = mUnion.table->Iter(); !iter.Done(); iter.Next()) {
      87           0 :           auto entry = static_cast<EntryType*>(iter.Get());
      88           0 :           if (aEnumFunc(entry, aUserArg) == OpRemove) {
      89           0 :             iter.Remove();
      90             :           }
      91             :         }
      92           0 :         return n;
      93             :       }
      94             :       default:
      95           0 :         NS_NOTREACHED("bogus state");
      96           0 :         return 0;
      97             :     }
      98             :   }
      99             : 
     100             : private:
     101           0 :   EntryType* GetSingleEntry()
     102             :   {
     103           0 :     return reinterpret_cast<EntryType*>(&mUnion.singleEntry[0]);
     104             :   }
     105             : 
     106             :   enum SetState
     107             :   {
     108             :     ZERO,
     109             :     ONE,
     110             :     MANY
     111             :   };
     112             : 
     113             :   union
     114             :   {
     115             :     nsTHashtable<EntryType>* table;
     116             :     char singleEntry[sizeof(EntryType)];
     117             :   } mUnion;
     118             :   enum SetState mState;
     119             : };
     120             : 
     121             : template<typename EntryType>
     122             : void
     123           0 : nsCheapSet<EntryType>::Put(const KeyType aVal)
     124             : {
     125           0 :   switch (mState) {
     126             :     case ZERO:
     127           0 :       new (GetSingleEntry()) EntryType(EntryType::KeyToPointer(aVal));
     128           0 :       mState = ONE;
     129           0 :       return;
     130             :     case ONE: {
     131           0 :       nsTHashtable<EntryType>* table = new nsTHashtable<EntryType>();
     132           0 :       EntryType* entry = GetSingleEntry();
     133           0 :       table->PutEntry(entry->GetKey());
     134           0 :       entry->~EntryType();
     135           0 :       mUnion.table = table;
     136           0 :       mState = MANY;
     137             :     }
     138             :     MOZ_FALLTHROUGH;
     139             : 
     140             :     case MANY:
     141           0 :       mUnion.table->PutEntry(aVal);
     142           0 :       return;
     143             :     default:
     144           0 :       NS_NOTREACHED("bogus state");
     145           0 :       return;
     146             :   }
     147             : }
     148             : 
     149             : template<typename EntryType>
     150             : void
     151           0 : nsCheapSet<EntryType>::Remove(const KeyType aVal)
     152             : {
     153           0 :   switch (mState) {
     154             :     case ZERO:
     155           0 :       break;
     156             :     case ONE:
     157           0 :       if (Contains(aVal)) {
     158           0 :         GetSingleEntry()->~EntryType();
     159           0 :         mState = ZERO;
     160             :       }
     161           0 :       break;
     162             :     case MANY:
     163           0 :       mUnion.table->RemoveEntry(aVal);
     164           0 :       break;
     165             :     default:
     166           0 :       NS_NOTREACHED("bogus state");
     167           0 :       break;
     168             :   }
     169           0 : }
     170             : 
     171             : #endif

Generated by: LCOV version 1.13