1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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. */
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
;
22 explicit NameTableKey(const nsAFlatCString
* aKeyStr
)
25 mKeyStr
.m1b
= aKeyStr
;
28 explicit NameTableKey(const nsAFlatString
* aKeyStr
)
31 mKeyStr
.m2b
= aKeyStr
;
37 const nsAFlatCString
* m1b
;
38 const nsAFlatString
* m2b
;
42 struct NameTableEntry
: public PLDHashEntryHdr
45 const nsAFlatCString
* mString
;
50 matchNameKeysCaseInsensitive(PLDHashTable
*, const PLDHashEntryHdr
* aHdr
,
53 const NameTableEntry
* entry
= static_cast<const NameTableEntry
*>(aHdr
);
54 const NameTableKey
* keyValue
= static_cast<const NameTableKey
*>(aKey
);
55 const nsAFlatCString
* entryKey
= entry
->mString
;
57 if (keyValue
->mIsUnichar
) {
58 return keyValue
->mKeyStr
.m2b
->LowerCaseEqualsASCII(entryKey
->get(),
62 return keyValue
->mKeyStr
.m1b
->LowerCaseEqualsASCII(entryKey
->get(),
67 * caseInsensitiveHashKey is just like PL_DHashStringKey except it
68 * uses (*s & ~0x20) instead of simply *s. This means that "aFOO" and
69 * "afoo" and "aFoo" will all hash to the same thing. It also means
70 * that some strings that aren't case-insensensitively equal will hash
71 * to the same value, but it's just a hash function so it doesn't
75 caseInsensitiveStringHashKey(PLDHashTable
* aTable
, const void* aKey
)
78 const NameTableKey
* tableKey
= static_cast<const NameTableKey
*>(aKey
);
79 if (tableKey
->mIsUnichar
) {
80 for (const char16_t
* s
= tableKey
->mKeyStr
.m2b
->get();
83 h
= AddToHash(h
, *s
& ~0x20);
86 for (const unsigned char* s
= reinterpret_cast<const unsigned char*>(
87 tableKey
->mKeyStr
.m1b
->get());
90 h
= AddToHash(h
, *s
& ~0x20);
96 static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps
= {
99 caseInsensitiveStringHashKey
,
100 matchNameKeysCaseInsensitive
,
101 PL_DHashMoveEntryStub
,
102 PL_DHashClearEntryStub
,
103 PL_DHashFinalizeStub
,
107 nsStaticCaseInsensitiveNameTable::nsStaticCaseInsensitiveNameTable()
108 : mNameArray(nullptr)
111 MOZ_COUNT_CTOR(nsStaticCaseInsensitiveNameTable
);
112 mNameTable
.ops
= nullptr;
115 nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
118 // manually call the destructor on placement-new'ed objects
119 for (uint32_t index
= 0; index
< mNameTable
.EntryCount(); index
++) {
120 mNameArray
[index
].~nsDependentCString();
122 nsMemory::Free((void*)mNameArray
);
124 if (mNameTable
.ops
) {
125 PL_DHashTableFinish(&mNameTable
);
127 MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable
);
131 nsStaticCaseInsensitiveNameTable::Init(const char* const aNames
[],
134 NS_ASSERTION(!mNameArray
, "double Init");
135 NS_ASSERTION(!mNameTable
.ops
, "double Init");
136 NS_ASSERTION(aNames
, "null name table");
137 NS_ASSERTION(aLength
, "0 length");
139 mNameArray
= (nsDependentCString
*)
140 nsMemory::Alloc(aLength
* sizeof(nsDependentCString
));
145 if (!PL_DHashTableInit(&mNameTable
, &nametable_CaseInsensitiveHashTableOps
,
146 nullptr, sizeof(NameTableEntry
), fallible_t(),
148 mNameTable
.ops
= nullptr;
152 for (int32_t index
= 0; index
< aLength
; ++index
) {
153 const char* raw
= aNames
[index
];
156 // verify invariants of contents
157 nsAutoCString
temp1(raw
);
158 nsDependentCString
temp2(raw
);
160 NS_ASSERTION(temp1
.Equals(temp2
), "upper case char in table");
161 NS_ASSERTION(nsCRT::IsAscii(raw
),
162 "non-ascii string in table -- "
163 "case-insensitive matching won't work right");
166 // use placement-new to initialize the string object
167 nsDependentCString
* strPtr
= &mNameArray
[index
];
168 new (strPtr
) nsDependentCString(raw
);
170 NameTableKey
key(strPtr
);
172 NameTableEntry
* entry
=
173 static_cast<NameTableEntry
*>(PL_DHashTableOperate(&mNameTable
, &key
,
179 NS_ASSERTION(entry
->mString
== 0, "Entry already exists!");
181 entry
->mString
= strPtr
; // not owned!
182 entry
->mIndex
= index
;
185 PL_DHashMarkTableImmutable(&mNameTable
);
191 nsStaticCaseInsensitiveNameTable::Lookup(const nsACString
& aName
)
193 NS_ASSERTION(mNameArray
, "not inited");
194 NS_ASSERTION(mNameTable
.ops
, "not inited");
196 const nsAFlatCString
& str
= PromiseFlatCString(aName
);
198 NameTableKey
key(&str
);
199 NameTableEntry
* entry
=
200 static_cast<NameTableEntry
*>(PL_DHashTableOperate(&mNameTable
, &key
,
202 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
203 return nsStaticCaseInsensitiveNameTable::NOT_FOUND
;
206 return entry
->mIndex
;
210 nsStaticCaseInsensitiveNameTable::Lookup(const nsAString
& aName
)
212 NS_ASSERTION(mNameArray
, "not inited");
213 NS_ASSERTION(mNameTable
.ops
, "not inited");
215 const nsAFlatString
& str
= PromiseFlatString(aName
);
217 NameTableKey
key(&str
);
218 NameTableEntry
* entry
=
219 static_cast<NameTableEntry
*>(PL_DHashTableOperate(&mNameTable
, &key
,
221 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
222 return nsStaticCaseInsensitiveNameTable::NOT_FOUND
;
225 return entry
->mIndex
;
228 const nsAFlatCString
&
229 nsStaticCaseInsensitiveNameTable::GetStringValue(int32_t aIndex
)
231 NS_ASSERTION(mNameArray
, "not inited");
232 NS_ASSERTION(mNameTable
.ops
, "not inited");
234 if ((NOT_FOUND
< aIndex
) && ((uint32_t)aIndex
< mNameTable
.EntryCount())) {
235 return mNameArray
[aIndex
];