xpcom/ds/nsCheapSets.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef __nsCheapSets_h__
     7 #define __nsCheapSets_h__
     9 #include "nsTHashtable.h"
    10 #include <stdint.h>
    12 /**
    13  * A set that takes up minimal size when there are 0 or 1 entries in the set.
    14  * Use for cases where sizes of 0 and 1 are even slightly common.
    15  */
    16 template<typename EntryType>
    17 class nsCheapSet
    18 {
    19 public:
    20   typedef typename EntryType::KeyType KeyType;
    21   typedef PLDHashOperator (* Enumerator)(EntryType* aEntry, void* userArg);
    23   nsCheapSet() : mState(ZERO)
    24   {
    25   }
    26   ~nsCheapSet()
    27   {
    28     switch (mState) {
    29     case ZERO:
    30       break;
    31     case ONE:
    32       GetSingleEntry()->~EntryType();
    33       break;
    34     case MANY:
    35       delete mUnion.table;
    36       break;
    37     default:
    38       NS_NOTREACHED("bogus state");
    39       break;
    40     }
    41   }
    43   nsresult Put(const KeyType aVal);
    45   void Remove(const KeyType aVal);
    47   bool Contains(const KeyType aVal)
    48   {
    49     switch (mState) {
    50     case ZERO:
    51       return false;
    52     case ONE:
    53       return GetSingleEntry()->KeyEquals(EntryType::KeyToPointer(aVal));
    54     case MANY:
    55       return !!mUnion.table->GetEntry(aVal);
    56     default:
    57       NS_NOTREACHED("bogus state");
    58       return false;
    59     }
    60   }
    62   uint32_t EnumerateEntries(Enumerator enumFunc, void* userArg)
    63   {
    64     switch (mState) {
    65     case ZERO:
    66       return 0;
    67     case ONE:
    68       if (enumFunc(GetSingleEntry(), userArg) == PL_DHASH_REMOVE) {
    69         GetSingleEntry()->~EntryType();
    70         mState = ZERO;
    71       }
    72       return 1;
    73     case MANY:
    74       return mUnion.table->EnumerateEntries(enumFunc, userArg);
    75     default:
    76       NS_NOTREACHED("bogus state");
    77       return 0;
    78     }
    79   }
    81 private:
    82   EntryType* GetSingleEntry()
    83   {
    84     return reinterpret_cast<EntryType*>(&mUnion.singleEntry[0]);
    85   }
    87   enum SetState {
    88     ZERO,
    89     ONE,
    90     MANY
    91   };
    93   union {
    94     nsTHashtable<EntryType> *table;
    95     char singleEntry[sizeof(EntryType)];
    96   } mUnion;
    97   enum SetState mState;
    98 };
   100 template<typename EntryType>
   101 nsresult
   102 nsCheapSet<EntryType>::Put(const KeyType aVal)
   103 {
   104   switch (mState) {
   105   case ZERO:
   106     new (GetSingleEntry()) EntryType(EntryType::KeyToPointer(aVal));
   107     mState = ONE;
   108     return NS_OK;
   109   case ONE:
   110     {
   111       nsTHashtable<EntryType> *table = new nsTHashtable<EntryType>();
   112       EntryType *entry = GetSingleEntry();
   113       table->PutEntry(entry->GetKey());
   114       entry->~EntryType();
   115       mUnion.table = table;
   116       mState = MANY;
   117     }
   118     // Fall through.
   119   case MANY:
   120     mUnion.table->PutEntry(aVal);
   121     return NS_OK;
   122   default:
   123     NS_NOTREACHED("bogus state");
   124     return NS_OK;
   125   }
   126 }
   128 template<typename EntryType>
   129 void
   130 nsCheapSet<EntryType>::Remove(const KeyType aVal)
   131 {
   132   switch (mState) {
   133   case ZERO:
   134     break;
   135   case ONE:
   136     if (Contains(aVal)) {
   137       GetSingleEntry()->~EntryType();
   138       mState = ZERO;
   139     }
   140     break;
   141   case MANY:
   142     mUnion.table->RemoveEntry(aVal);
   143     break;
   144   default:
   145     NS_NOTREACHED("bogus state");
   146     break;
   147   }
   148 }
   150 #endif

mercurial