VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40/* Class to manage lookup of static names in a table. */
41
42#include "nsCRT.h"
43
44#include "nscore.h"
45#include "nsString.h"
46#include "nsReadableUtils.h"
47
48#define PL_ARENA_CONST_ALIGN_MASK 3
49#include "nsStaticNameTable.h"
50
51struct NameTableEntry : public PLDHashEntryHdr
52{
53 // no ownership here!
54 const char *mKey;
55 PRInt32 mIndex;
56};
57
58PR_STATIC_CALLBACK(PRBool)
59matchNameKeysCaseInsensitive(PLDHashTable*, const PLDHashEntryHdr* aHdr,
60 const void* key)
61{
62 const NameTableEntry* entry =
63 NS_STATIC_CAST(const NameTableEntry *, aHdr);
64 const char *keyValue = NS_STATIC_CAST(const char*, key);
65
66 return (nsCRT::strcasecmp(entry->mKey, keyValue)==0);
67}
68
69/*
70 * caseInsensitiveHashKey is just like PL_DHashStringKey except it
71 * uses (*s & ~0x20) instead of simply *s. This means that "aFOO" and
72 * "afoo" and "aFoo" will all hash to the same thing. It also means
73 * that some strings that aren't case-insensensitively equal will hash
74 * to the same value, but it's just a hash function so it doesn't
75 * matter.
76 */
77PR_STATIC_CALLBACK(PLDHashNumber)
78caseInsensitiveStringHashKey(PLDHashTable *table, const void *key)
79{
80 PLDHashNumber h = 0;
81 for (const unsigned char* s =
82 NS_STATIC_CAST(const unsigned char*, key);
83 *s != '\0';
84 s++)
85 h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ (*s & ~0x20);
86 return h;
87}
88
89static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps = {
90 PL_DHashAllocTable,
91 PL_DHashFreeTable,
92 PL_DHashGetKeyStub,
93 caseInsensitiveStringHashKey,
94 matchNameKeysCaseInsensitive,
95 PL_DHashMoveEntryStub,
96 PL_DHashClearEntryStub,
97 PL_DHashFinalizeStub,
98 nsnull,
99};
100
101nsStaticCaseInsensitiveNameTable::nsStaticCaseInsensitiveNameTable()
102 : mNameArray(nsnull), mNullStr("")
103{
104 MOZ_COUNT_CTOR(nsStaticCaseInsensitiveNameTable);
105 mNameTable.ops = nsnull;
106}
107
108nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
109{
110 if (mNameArray) {
111 // manually call the destructor on placement-new'ed objects
112 for (PRUint32 index = 0; index < mNameTable.entryCount; index++) {
113 mNameArray[index].~nsDependentCString();
114 }
115 nsMemory::Free((void*)mNameArray);
116 }
117 if (mNameTable.ops)
118 PL_DHashTableFinish(&mNameTable);
119 MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable);
120}
121
122PRBool
123nsStaticCaseInsensitiveNameTable::Init(const char* const aNames[], PRInt32 Count)
124{
125 NS_ASSERTION(!mNameArray, "double Init");
126 NS_ASSERTION(!mNameTable.ops, "double Init");
127 NS_ASSERTION(aNames, "null name table");
128 NS_ASSERTION(Count, "0 count");
129
130 mNameArray = (nsDependentCString*)
131 nsMemory::Alloc(Count * sizeof(nsDependentCString));
132 if (!mNameArray)
133 return PR_FALSE;
134
135 if (!PL_DHashTableInit(&mNameTable,
136 &nametable_CaseInsensitiveHashTableOps,
137 nsnull, sizeof(NameTableEntry), Count)) {
138 mNameTable.ops = nsnull;
139 return PR_FALSE;
140 }
141
142 for (PRInt32 index = 0; index < Count; ++index) {
143 const char* raw = aNames[index];
144#ifdef DEBUG
145 {
146 // verify invariants of contents
147 nsCAutoString temp1(raw);
148 nsDependentCString temp2(raw);
149 ToLowerCase(temp1);
150 NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
151 NS_ASSERTION(nsCRT::IsAscii(raw),
152 "non-ascii string in table -- "
153 "case-insensitive matching won't work right");
154 }
155#endif
156 // use placement-new to initialize the string object
157 new (&mNameArray[index]) nsDependentCString(raw);
158
159 NameTableEntry *entry =
160 NS_STATIC_CAST(NameTableEntry*,
161 PL_DHashTableOperate(&mNameTable, raw, PL_DHASH_ADD));
162
163 if (!entry) continue;
164
165 NS_ASSERTION(entry->mKey == 0, "Entry already exists!");
166
167 entry->mKey = raw; // not owned!
168 entry->mIndex = index;
169 }
170 return PR_TRUE;
171}
172
173inline PRInt32
174LookupFlatKeyword(const nsAFlatCString& aKeyword,
175 PLDHashTable& aTable)
176{
177 NameTableEntry *entry =
178 NS_STATIC_CAST(NameTableEntry*,
179 PL_DHashTableOperate(&aTable, aKeyword.get(), PL_DHASH_LOOKUP));
180
181 if (PL_DHASH_ENTRY_IS_FREE(entry))
182 return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
183
184 return entry->mIndex;
185}
186
187PRInt32
188nsStaticCaseInsensitiveNameTable::Lookup(const nsACString& aName)
189{
190 NS_ASSERTION(mNameArray, "not inited");
191 NS_ASSERTION(mNameTable.ops, "not inited");
192
193 return LookupFlatKeyword(PromiseFlatCString(aName), mNameTable);
194}
195
196PRInt32
197nsStaticCaseInsensitiveNameTable::Lookup(const nsAString& aName)
198{
199 NS_ASSERTION(mNameArray, "not inited");
200 NS_ASSERTION(mNameTable.ops, "not inited");
201
202 nsCAutoString cstring;
203 cstring.AssignWithConversion(aName);
204 return LookupFlatKeyword(cstring, mNameTable);
205}
206
207const nsAFlatCString&
208nsStaticCaseInsensitiveNameTable::GetStringValue(PRInt32 index)
209{
210 NS_ASSERTION(mNameArray, "not inited");
211 NS_ASSERTION(mNameTable.ops, "not inited");
212
213 if ((NOT_FOUND < index) && ((PRUint32)index < mNameTable.entryCount)) {
214 return mNameArray[index];
215 }
216 return mNullStr;
217}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use