xpcom/ds/nsStaticNameTable.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial