1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "xpcom-config.h"
39 : #include NEW_H // for placement new
40 : #include "nscore.h"
41 : #include "nsCRT.h"
42 :
43 : #include "nsCommandParams.h"
44 : #include "mozilla/HashFunctions.h"
45 :
46 : using namespace mozilla;
47 :
48 : PLDHashTableOps nsCommandParams::sHashOps =
49 : {
50 : PL_DHashAllocTable,
51 : PL_DHashFreeTable,
52 : HashKey,
53 : HashMatchEntry,
54 : HashMoveEntry,
55 : HashClearEntry,
56 : PL_DHashFinalizeStub
57 : };
58 :
59 :
60 0 : NS_IMPL_ISUPPORTS1(nsCommandParams, nsICommandParams)
61 :
62 0 : nsCommandParams::nsCommandParams()
63 : : mCurEntry(0)
64 0 : , mNumEntries(eNumEntriesUnknown)
65 : {
66 : // init the hash table later
67 0 : }
68 :
69 0 : nsCommandParams::~nsCommandParams()
70 : {
71 0 : PL_DHashTableFinish(&mValuesHash);
72 0 : }
73 :
74 : nsresult
75 0 : nsCommandParams::Init()
76 : {
77 0 : if (!PL_DHashTableInit(&mValuesHash, &sHashOps, (void *)this, sizeof(HashEntry), 4))
78 0 : return NS_ERROR_FAILURE;
79 :
80 0 : return NS_OK;
81 : }
82 :
83 : #if 0
84 : #pragma mark -
85 : #endif
86 :
87 : /* short getValueType (in string name); */
88 0 : NS_IMETHODIMP nsCommandParams::GetValueType(const char * name, PRInt16 *_retval)
89 : {
90 0 : NS_ENSURE_ARG_POINTER(_retval);
91 0 : *_retval = eNoType;
92 0 : HashEntry* foundEntry = GetNamedEntry(name);
93 0 : if (foundEntry)
94 : {
95 0 : *_retval = foundEntry->mEntryType;
96 0 : return NS_OK;
97 : }
98 :
99 0 : return NS_ERROR_FAILURE;
100 : }
101 :
102 : /* boolean getBooleanValue (in AString name); */
103 0 : NS_IMETHODIMP nsCommandParams::GetBooleanValue(const char * name, bool *_retval)
104 : {
105 0 : NS_ENSURE_ARG_POINTER(_retval);
106 0 : *_retval = false;
107 :
108 0 : HashEntry* foundEntry = GetNamedEntry(name);
109 0 : if (foundEntry && foundEntry->mEntryType == eBooleanType)
110 : {
111 0 : *_retval = foundEntry->mData.mBoolean;
112 0 : return NS_OK;
113 : }
114 :
115 0 : return NS_ERROR_FAILURE;
116 : }
117 :
118 : /* long getLongValue (in AString name); */
119 0 : NS_IMETHODIMP nsCommandParams::GetLongValue(const char * name, PRInt32 *_retval)
120 : {
121 0 : NS_ENSURE_ARG_POINTER(_retval);
122 0 : *_retval = false;
123 :
124 0 : HashEntry* foundEntry = GetNamedEntry(name);
125 0 : if (foundEntry && foundEntry->mEntryType == eLongType)
126 : {
127 0 : *_retval = foundEntry->mData.mLong;
128 0 : return NS_OK;
129 : }
130 :
131 0 : return NS_ERROR_FAILURE;
132 : }
133 :
134 : /* double getDoubleValue (in AString name); */
135 0 : NS_IMETHODIMP nsCommandParams::GetDoubleValue(const char * name, double *_retval)
136 : {
137 0 : NS_ENSURE_ARG_POINTER(_retval);
138 0 : *_retval = 0.0;
139 :
140 0 : HashEntry* foundEntry = GetNamedEntry(name);
141 0 : if (foundEntry && foundEntry->mEntryType == eDoubleType)
142 : {
143 0 : *_retval = foundEntry->mData.mDouble;
144 0 : return NS_OK;
145 : }
146 :
147 0 : return NS_ERROR_FAILURE;
148 : }
149 :
150 : /* AString getStringValue (in AString name); */
151 0 : NS_IMETHODIMP nsCommandParams::GetStringValue(const char *name, nsAString & _retval)
152 : {
153 0 : _retval.Truncate();
154 0 : HashEntry* foundEntry = GetNamedEntry(name);
155 0 : if (foundEntry && foundEntry->mEntryType == eWStringType)
156 : {
157 0 : NS_ASSERTION(foundEntry->mData.mString, "Null string");
158 0 : _retval.Assign(*foundEntry->mData.mString);
159 0 : return NS_OK;
160 : }
161 :
162 0 : return NS_ERROR_FAILURE;
163 : }
164 :
165 : /* AString getStringValue (in AString name); */
166 0 : NS_IMETHODIMP nsCommandParams::GetCStringValue(const char * name, char **_retval)
167 : {
168 0 : HashEntry* foundEntry = GetNamedEntry(name);
169 0 : if (foundEntry && foundEntry->mEntryType == eStringType)
170 : {
171 0 : NS_ASSERTION(foundEntry->mData.mCString, "Null string");
172 0 : *_retval = ToNewCString(*foundEntry->mData.mCString);
173 0 : return NS_OK;
174 : }
175 :
176 0 : return NS_ERROR_FAILURE;
177 : }
178 :
179 : /* nsISupports getISupportsValue (in AString name); */
180 0 : NS_IMETHODIMP nsCommandParams::GetISupportsValue(const char * name, nsISupports **_retval)
181 : {
182 0 : NS_ENSURE_ARG_POINTER(_retval);
183 0 : *_retval = nsnull;
184 :
185 0 : HashEntry* foundEntry = GetNamedEntry(name);
186 0 : if (foundEntry && foundEntry->mEntryType == eISupportsType)
187 : {
188 0 : NS_IF_ADDREF(*_retval = foundEntry->mISupports.get());
189 0 : return NS_OK;
190 : }
191 :
192 0 : return NS_ERROR_FAILURE;
193 : }
194 :
195 : #if 0
196 : #pragma mark -
197 : #endif
198 :
199 : /* void setBooleanValue (in AString name, in boolean value); */
200 0 : NS_IMETHODIMP nsCommandParams::SetBooleanValue(const char * name, bool value)
201 : {
202 : HashEntry* foundEntry;
203 0 : GetOrMakeEntry(name, eBooleanType, foundEntry);
204 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
205 :
206 0 : foundEntry->mData.mBoolean = value;
207 :
208 0 : return NS_OK;
209 : }
210 :
211 : /* void setLongValue (in AString name, in long value); */
212 0 : NS_IMETHODIMP nsCommandParams::SetLongValue(const char * name, PRInt32 value)
213 : {
214 : HashEntry* foundEntry;
215 0 : GetOrMakeEntry(name, eLongType, foundEntry);
216 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
217 :
218 0 : foundEntry->mData.mLong = value;
219 0 : return NS_OK;
220 : }
221 :
222 : /* void setDoubleValue (in AString name, in double value); */
223 0 : NS_IMETHODIMP nsCommandParams::SetDoubleValue(const char * name, double value)
224 : {
225 : HashEntry* foundEntry;
226 0 : GetOrMakeEntry(name, eDoubleType, foundEntry);
227 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
228 :
229 0 : foundEntry->mData.mDouble = value;
230 0 : return NS_OK;
231 : }
232 :
233 : /* void setStringValue (in AString name, in AString value); */
234 0 : NS_IMETHODIMP nsCommandParams::SetStringValue(const char * name, const nsAString & value)
235 : {
236 : HashEntry* foundEntry;
237 0 : GetOrMakeEntry(name, eWStringType, foundEntry);
238 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
239 :
240 0 : foundEntry->mData.mString = new nsString(value);
241 0 : return NS_OK;
242 : }
243 :
244 : /* void setCStringValue (in string name, in string value); */
245 0 : NS_IMETHODIMP nsCommandParams::SetCStringValue(const char * name, const char * value)
246 : {
247 : HashEntry* foundEntry;
248 0 : GetOrMakeEntry(name, eStringType, foundEntry);
249 0 : if (!foundEntry)
250 0 : return NS_ERROR_OUT_OF_MEMORY;
251 0 : foundEntry->mData.mCString = new nsCString(value);
252 0 : return NS_OK;
253 : }
254 :
255 : /* void setISupportsValue (in AString name, in nsISupports value); */
256 0 : NS_IMETHODIMP nsCommandParams::SetISupportsValue(const char * name, nsISupports *value)
257 : {
258 : HashEntry* foundEntry;
259 0 : GetOrMakeEntry(name, eISupportsType, foundEntry);
260 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
261 :
262 0 : foundEntry->mISupports = value; // addrefs
263 0 : return NS_OK;
264 : }
265 :
266 : /* void removeValue (in AString name); */
267 : NS_IMETHODIMP
268 0 : nsCommandParams::RemoveValue(const char * name)
269 : {
270 : // PL_DHASH_REMOVE doesn't tell us if the entry was really removed, so we return
271 : // NS_OK unconditionally.
272 0 : (void)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_REMOVE);
273 :
274 : // inval the number of entries
275 0 : mNumEntries = eNumEntriesUnknown;
276 0 : return NS_OK;
277 : }
278 :
279 : #if 0
280 : #pragma mark -
281 : #endif
282 :
283 : nsCommandParams::HashEntry*
284 0 : nsCommandParams::GetNamedEntry(const char * name)
285 : {
286 0 : HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP);
287 :
288 0 : if (PL_DHASH_ENTRY_IS_BUSY(foundEntry))
289 0 : return foundEntry;
290 :
291 0 : return nsnull;
292 : }
293 :
294 :
295 : nsCommandParams::HashEntry*
296 0 : nsCommandParams::GetIndexedEntry(PRInt32 index)
297 : {
298 0 : HashEntry* entry = reinterpret_cast<HashEntry*>(mValuesHash.entryStore);
299 0 : HashEntry* limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash);
300 0 : PRUint32 entryCount = 0;
301 :
302 0 : do
303 : {
304 0 : if (!PL_DHASH_ENTRY_IS_LIVE(entry))
305 0 : continue;
306 :
307 0 : if ((PRInt32)entryCount == index)
308 0 : return entry;
309 :
310 0 : entryCount ++;
311 : } while (++entry < limit);
312 :
313 0 : return nsnull;
314 : }
315 :
316 :
317 : PRUint32
318 0 : nsCommandParams::GetNumEntries()
319 : {
320 0 : HashEntry* entry = reinterpret_cast<HashEntry*>(mValuesHash.entryStore);
321 0 : HashEntry* limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash);
322 0 : PRUint32 entryCount = 0;
323 :
324 0 : do
325 : {
326 0 : if (PL_DHASH_ENTRY_IS_LIVE(entry))
327 0 : entryCount ++;
328 : } while (++entry < limit);
329 :
330 0 : return entryCount;
331 : }
332 :
333 : nsresult
334 0 : nsCommandParams::GetOrMakeEntry(const char * name, PRUint8 entryType, HashEntry*& outEntry)
335 : {
336 :
337 0 : HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP);
338 0 : if (PL_DHASH_ENTRY_IS_BUSY(foundEntry)) // reuse existing entry
339 : {
340 0 : foundEntry->Reset(entryType);
341 0 : foundEntry->mEntryName.Assign(name);
342 0 : outEntry = foundEntry;
343 0 : return NS_OK;
344 : }
345 :
346 0 : foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_ADD);
347 0 : if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
348 :
349 : // placement new that sucker. Our ctor does not clobber keyHash, which is important.
350 0 : outEntry = new (foundEntry) HashEntry(entryType, name);
351 0 : return NS_OK;
352 : }
353 :
354 : #if 0
355 : #pragma mark -
356 : #endif
357 :
358 : PLDHashNumber
359 0 : nsCommandParams::HashKey(PLDHashTable *table, const void *key)
360 : {
361 0 : return HashString((const char *)key);
362 : }
363 :
364 : bool
365 0 : nsCommandParams::HashMatchEntry(PLDHashTable *table,
366 : const PLDHashEntryHdr *entry, const void *key)
367 : {
368 0 : const char* keyString = (const char*)key;
369 0 : const HashEntry* thisEntry = static_cast<const HashEntry*>(entry);
370 :
371 0 : return thisEntry->mEntryName.Equals(keyString);
372 : }
373 :
374 : void
375 0 : nsCommandParams::HashMoveEntry(PLDHashTable *table, const PLDHashEntryHdr *from,
376 : PLDHashEntryHdr *to)
377 : {
378 0 : const HashEntry* fromEntry = static_cast<const HashEntry*>(from);
379 0 : HashEntry* toEntry = static_cast<HashEntry*>(to);
380 :
381 0 : *toEntry = *fromEntry;
382 : // we leave from dirty, but that's OK
383 0 : }
384 :
385 : void
386 0 : nsCommandParams::HashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
387 : {
388 0 : HashEntry* thisEntry = static_cast<HashEntry*>(entry);
389 0 : thisEntry->~HashEntry(); // call dtor explicitly
390 0 : memset(thisEntry, 0, sizeof(HashEntry)); // and clear out
391 0 : }
392 :
393 : #if 0
394 : #pragma mark -
395 : #endif
396 :
397 : /* boolean hasMoreElements (); */
398 : NS_IMETHODIMP
399 0 : nsCommandParams::HasMoreElements(bool *_retval)
400 : {
401 0 : NS_ENSURE_ARG_POINTER(_retval);
402 :
403 0 : if (mNumEntries == eNumEntriesUnknown)
404 0 : mNumEntries = GetNumEntries();
405 :
406 0 : *_retval = mCurEntry < mNumEntries;
407 0 : return NS_OK;
408 : }
409 :
410 : /* void first (); */
411 : NS_IMETHODIMP
412 0 : nsCommandParams::First()
413 : {
414 0 : mCurEntry = 0;
415 0 : return NS_OK;
416 : }
417 :
418 : /* AString getNext (); */
419 : NS_IMETHODIMP
420 0 : nsCommandParams::GetNext(char **_retval)
421 : {
422 0 : HashEntry* thisEntry = GetIndexedEntry(mCurEntry);
423 0 : if (!thisEntry)
424 0 : return NS_ERROR_FAILURE;
425 :
426 0 : *_retval = ToNewCString(thisEntry->mEntryName);
427 0 : mCurEntry++;
428 0 : return NS_OK;
429 : }
|