xpcom/ds/nsStaticNameTable.cpp

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: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     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/. */
     7 /* Class to manage lookup of static names in a table. */
     9 #include "nsCRT.h"
    11 #include "nscore.h"
    12 #include "mozilla/HashFunctions.h"
    13 #include "nsISupportsImpl.h"
    15 #define PL_ARENA_CONST_ALIGN_MASK 3
    16 #include "nsStaticNameTable.h"
    18 using namespace mozilla;
    20 struct NameTableKey
    21 {
    22     NameTableKey(const nsAFlatCString* aKeyStr)
    23         : mIsUnichar(false)
    24     {
    25         mKeyStr.m1b = aKeyStr;
    26     }
    28     NameTableKey(const nsAFlatString* aKeyStr)
    29         : mIsUnichar(true)
    30     {
    31         mKeyStr.m2b = aKeyStr;
    32     }
    34     bool mIsUnichar;
    35     union {
    36         const nsAFlatCString* m1b;
    37         const nsAFlatString* m2b;
    38     } mKeyStr;
    39 };
    41 struct NameTableEntry : public PLDHashEntryHdr
    42 {
    43     // no ownership here!
    44     const nsAFlatCString* mString;
    45     int32_t mIndex;
    46 };
    48 static bool
    49 matchNameKeysCaseInsensitive(PLDHashTable*, const PLDHashEntryHdr* aHdr,
    50                              const void* key)
    51 {
    52     const NameTableEntry* entry =
    53         static_cast<const NameTableEntry *>(aHdr);
    54     const NameTableKey *keyValue = static_cast<const NameTableKey*>(key);
    56     const nsAFlatCString* entryKey = entry->mString;
    58     if (keyValue->mIsUnichar) {
    59         return keyValue->mKeyStr.m2b->
    60             LowerCaseEqualsASCII(entryKey->get(), entryKey->Length());
    61     }
    63     return keyValue->mKeyStr.m1b->
    64         LowerCaseEqualsASCII(entryKey->get(), entryKey->Length());
    65 }
    67 /*
    68  * caseInsensitiveHashKey is just like PL_DHashStringKey except it
    69  * uses (*s & ~0x20) instead of simply *s.  This means that "aFOO" and
    70  * "afoo" and "aFoo" will all hash to the same thing.  It also means
    71  * that some strings that aren't case-insensensitively equal will hash
    72  * to the same value, but it's just a hash function so it doesn't
    73  * matter.
    74  */
    75 static PLDHashNumber
    76 caseInsensitiveStringHashKey(PLDHashTable *table, const void *key)
    77 {
    78     PLDHashNumber h = 0;
    79     const NameTableKey* tableKey = static_cast<const NameTableKey*>(key);
    80     if (tableKey->mIsUnichar) {
    81         for (const char16_t* s = tableKey->mKeyStr.m2b->get();
    82              *s != '\0';
    83              s++)
    84             h = AddToHash(h, *s & ~0x20);
    85     } else {
    86         for (const unsigned char* s =
    87                  reinterpret_cast<const unsigned char*>
    88                                  (tableKey->mKeyStr.m1b->get());
    89              *s != '\0';
    90              s++)
    91             h = AddToHash(h, *s & ~0x20);
    92     }
    93     return h;
    94 }
    96 static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps = {
    97     PL_DHashAllocTable,
    98     PL_DHashFreeTable,
    99     caseInsensitiveStringHashKey,
   100     matchNameKeysCaseInsensitive,
   101     PL_DHashMoveEntryStub,
   102     PL_DHashClearEntryStub,
   103     PL_DHashFinalizeStub,
   104     nullptr,
   105 };
   107 nsStaticCaseInsensitiveNameTable::nsStaticCaseInsensitiveNameTable()
   108   : mNameArray(nullptr), mNullStr("")
   109 {
   110     MOZ_COUNT_CTOR(nsStaticCaseInsensitiveNameTable);
   111     mNameTable.ops = nullptr;
   112 }
   114 nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
   115 {
   116     if (mNameArray) {
   117         // manually call the destructor on placement-new'ed objects
   118         for (uint32_t index = 0; index < mNameTable.entryCount; index++) {
   119             mNameArray[index].~nsDependentCString();
   120         }
   121         nsMemory::Free((void*)mNameArray);
   122     }
   123     if (mNameTable.ops)
   124         PL_DHashTableFinish(&mNameTable);
   125     MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable);
   126 }
   128 bool
   129 nsStaticCaseInsensitiveNameTable::Init(const char* const aNames[], int32_t Count)
   130 {
   131     NS_ASSERTION(!mNameArray, "double Init");
   132     NS_ASSERTION(!mNameTable.ops, "double Init");
   133     NS_ASSERTION(aNames, "null name table");
   134     NS_ASSERTION(Count, "0 count");
   136     mNameArray = (nsDependentCString*)
   137                    nsMemory::Alloc(Count * sizeof(nsDependentCString));
   138     if (!mNameArray)
   139         return false;
   141     if (!PL_DHashTableInit(&mNameTable, &nametable_CaseInsensitiveHashTableOps,
   142                            nullptr, sizeof(NameTableEntry), Count,
   143                            fallible_t())) {
   144         mNameTable.ops = nullptr;
   145         return false;
   146     }
   148     for (int32_t index = 0; index < Count; ++index) {
   149         const char* raw = aNames[index];
   150 #ifdef DEBUG
   151         {
   152             // verify invariants of contents
   153             nsAutoCString temp1(raw);
   154             nsDependentCString temp2(raw);
   155             ToLowerCase(temp1);
   156             NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
   157             NS_ASSERTION(nsCRT::IsAscii(raw),
   158                          "non-ascii string in table -- "
   159                          "case-insensitive matching won't work right");
   160         }
   161 #endif
   162         // use placement-new to initialize the string object
   163         nsDependentCString* strPtr = &mNameArray[index];
   164         new (strPtr) nsDependentCString(raw);
   166         NameTableKey key(strPtr);
   168         NameTableEntry *entry =
   169           static_cast<NameTableEntry*>
   170                      (PL_DHashTableOperate(&mNameTable, &key,
   171                                               PL_DHASH_ADD));
   173         if (!entry) continue;
   175         NS_ASSERTION(entry->mString == 0, "Entry already exists!");
   177         entry->mString = strPtr;      // not owned!
   178         entry->mIndex = index;
   179     }
   180 #ifdef DEBUG
   181     PL_DHashMarkTableImmutable(&mNameTable);
   182 #endif
   183     return true;
   184 }
   186 int32_t
   187 nsStaticCaseInsensitiveNameTable::Lookup(const nsACString& aName)
   188 {
   189     NS_ASSERTION(mNameArray, "not inited");
   190     NS_ASSERTION(mNameTable.ops, "not inited");
   192     const nsAFlatCString& str = PromiseFlatCString(aName);
   194     NameTableKey key(&str);
   195     NameTableEntry *entry =
   196         static_cast<NameTableEntry*>
   197                    (PL_DHashTableOperate(&mNameTable, &key,
   198                                             PL_DHASH_LOOKUP));
   200     if (PL_DHASH_ENTRY_IS_FREE(entry))
   201         return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
   203     return entry->mIndex;
   204 }
   206 int32_t
   207 nsStaticCaseInsensitiveNameTable::Lookup(const nsAString& aName)
   208 {
   209     NS_ASSERTION(mNameArray, "not inited");
   210     NS_ASSERTION(mNameTable.ops, "not inited");
   212     const nsAFlatString& str = PromiseFlatString(aName);
   214     NameTableKey key(&str);
   215     NameTableEntry *entry =
   216         static_cast<NameTableEntry*>
   217                    (PL_DHashTableOperate(&mNameTable, &key,
   218                                             PL_DHASH_LOOKUP));
   220     if (PL_DHASH_ENTRY_IS_FREE(entry))
   221         return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
   223     return entry->mIndex;
   224 }
   226 const nsAFlatCString& 
   227 nsStaticCaseInsensitiveNameTable::GetStringValue(int32_t index)
   228 {
   229     NS_ASSERTION(mNameArray, "not inited");
   230     NS_ASSERTION(mNameTable.ops, "not inited");
   232     if ((NOT_FOUND < index) && ((uint32_t)index < mNameTable.entryCount)) {
   233         return mNameArray[index];
   234     }
   235     return mNullStr;
   236 }

mercurial