Back to index

lightning-sunbird  0.9+nobinonly
nsCommandParams.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "xpcom-config.h"
00039 #include NEW_H    // for placement new
00040 #include "nscore.h"
00041 #include "nsCRT.h"
00042 
00043 #include "nsCommandParams.h"
00044 
00045 
00046 PLDHashTableOps nsCommandParams::sHashOps =
00047 {
00048     PL_DHashAllocTable,
00049     PL_DHashFreeTable,
00050     HashGetKey,
00051     HashKey,
00052     HashMatchEntry,
00053     HashMoveEntry,
00054     HashClearEntry,
00055     PL_DHashFinalizeStub
00056 };
00057 
00058 
00059 NS_IMPL_ISUPPORTS1(nsCommandParams, nsICommandParams)
00060 
00061 nsCommandParams::nsCommandParams()
00062 : mCurEntry(0)
00063 , mNumEntries(eNumEntriesUnknown)
00064 {
00065   // init the hash table later
00066 }
00067 
00068 nsCommandParams::~nsCommandParams()
00069 {
00070   PL_DHashTableFinish(&mValuesHash);
00071 }
00072 
00073 nsresult
00074 nsCommandParams::Init()
00075 {
00076   if (!PL_DHashTableInit(&mValuesHash, &sHashOps, (void *)this, sizeof(HashEntry), 4))
00077     return NS_ERROR_FAILURE;
00078     
00079   return NS_OK;
00080 }
00081 
00082 #if 0
00083 #pragma mark -
00084 #endif
00085 
00086 /* short getValueType (in string name); */
00087 NS_IMETHODIMP nsCommandParams::GetValueType(const char * name, PRInt16 *_retval)
00088 {
00089   NS_ENSURE_ARG_POINTER(_retval);
00090   *_retval = eNoType;
00091   HashEntry*  foundEntry = GetNamedEntry(name);
00092   if (foundEntry)
00093   {
00094     *_retval = foundEntry->mEntryType;
00095     return NS_OK;
00096   }
00097   
00098   return NS_ERROR_FAILURE;
00099 }
00100 
00101 /* boolean getBooleanValue (in AString name); */
00102 NS_IMETHODIMP nsCommandParams::GetBooleanValue(const char * name, PRBool *_retval)
00103 {
00104   NS_ENSURE_ARG_POINTER(_retval);
00105   *_retval = PR_FALSE;
00106 
00107   HashEntry*  foundEntry = GetNamedEntry(name);
00108   if (foundEntry && foundEntry->mEntryType == eBooleanType)
00109   {
00110     *_retval = foundEntry->mData.mBoolean;
00111     return NS_OK;
00112   }
00113   
00114   return NS_ERROR_FAILURE;
00115 }
00116 
00117 /* long getLongValue (in AString name); */
00118 NS_IMETHODIMP nsCommandParams::GetLongValue(const char * name, PRInt32 *_retval)
00119 {
00120   NS_ENSURE_ARG_POINTER(_retval);
00121   *_retval = PR_FALSE;
00122 
00123   HashEntry*  foundEntry = GetNamedEntry(name);
00124   if (foundEntry && foundEntry->mEntryType == eLongType)
00125   {
00126     *_retval = foundEntry->mData.mLong;
00127     return NS_OK;
00128   }
00129   
00130   return NS_ERROR_FAILURE;
00131 }
00132 
00133 /* double getDoubleValue (in AString name); */
00134 NS_IMETHODIMP nsCommandParams::GetDoubleValue(const char * name, double *_retval)
00135 {
00136   NS_ENSURE_ARG_POINTER(_retval);
00137   *_retval = 0.0;
00138 
00139   HashEntry*  foundEntry = GetNamedEntry(name);
00140   if (foundEntry && foundEntry->mEntryType == eDoubleType)
00141   {
00142     *_retval = foundEntry->mData.mDouble;
00143     return NS_OK;
00144   }
00145   
00146   return NS_ERROR_FAILURE;
00147 }
00148 
00149 /* AString getStringValue (in AString name); */
00150 NS_IMETHODIMP nsCommandParams::GetStringValue(const char *name, nsAString & _retval)
00151 {
00152   _retval.Truncate();
00153   HashEntry*  foundEntry = GetNamedEntry(name);
00154   if (foundEntry && foundEntry->mEntryType == eWStringType)
00155   {
00156     NS_ASSERTION(foundEntry->mData.mString, "Null string");
00157     _retval.Assign(*foundEntry->mData.mString);
00158     return NS_OK;
00159   }
00160   
00161   return NS_ERROR_FAILURE;
00162 }
00163 
00164 /* AString getStringValue (in AString name); */
00165 NS_IMETHODIMP nsCommandParams::GetCStringValue(const char * name, char **_retval)
00166 {
00167   HashEntry*  foundEntry = GetNamedEntry(name);
00168   if (foundEntry && foundEntry->mEntryType == eStringType)
00169   {
00170     NS_ASSERTION(foundEntry->mData.mCString, "Null string");
00171     *_retval= nsCRT::strdup((*foundEntry->mData.mCString).get());
00172     return NS_OK;
00173   }
00174   
00175   return NS_ERROR_FAILURE;
00176 }
00177 
00178 /* nsISupports getISupportsValue (in AString name); */
00179 NS_IMETHODIMP nsCommandParams::GetISupportsValue(const char * name, nsISupports **_retval)
00180 {
00181   NS_ENSURE_ARG_POINTER(_retval);
00182   *_retval = nsnull;
00183 
00184   HashEntry*  foundEntry = GetNamedEntry(name);
00185   if (foundEntry && foundEntry->mEntryType == eISupportsType)
00186   {
00187     NS_IF_ADDREF(*_retval = foundEntry->mISupports.get());
00188     return NS_OK;
00189   }
00190   
00191   return NS_ERROR_FAILURE;
00192 }
00193 
00194 #if 0
00195 #pragma mark -
00196 #endif
00197 
00198 /* void setBooleanValue (in AString name, in boolean value); */
00199 NS_IMETHODIMP nsCommandParams::SetBooleanValue(const char * name, PRBool value)
00200 {
00201   HashEntry*  foundEntry;
00202   GetOrMakeEntry(name, eBooleanType, foundEntry);
00203   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00204   
00205   foundEntry->mData.mBoolean = value;
00206   
00207   return NS_OK;
00208 }
00209 
00210 /* void setLongValue (in AString name, in long value); */
00211 NS_IMETHODIMP nsCommandParams::SetLongValue(const char * name, PRInt32 value)
00212 {
00213   HashEntry*  foundEntry;
00214   GetOrMakeEntry(name, eLongType, foundEntry);
00215   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00216   
00217   foundEntry->mData.mLong = value;
00218   return NS_OK;
00219 }
00220 
00221 /* void setDoubleValue (in AString name, in double value); */
00222 NS_IMETHODIMP nsCommandParams::SetDoubleValue(const char * name, double value)
00223 {
00224   HashEntry*  foundEntry;
00225   GetOrMakeEntry(name, eDoubleType, foundEntry);
00226   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00227   
00228   foundEntry->mData.mDouble = value;
00229   return NS_OK;
00230 }
00231 
00232 /* void setStringValue (in AString name, in AString value); */
00233 NS_IMETHODIMP nsCommandParams::SetStringValue(const char * name, const nsAString & value)
00234 {
00235   HashEntry*  foundEntry;
00236   GetOrMakeEntry(name, eWStringType, foundEntry);
00237   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00238   
00239   foundEntry->mData.mString = new nsString(value);
00240   return NS_OK;
00241 }
00242 
00243 /* void setCStringValue (in string name, in string value); */
00244 NS_IMETHODIMP nsCommandParams::SetCStringValue(const char * name, const char * value)
00245 {
00246   HashEntry*  foundEntry;
00247   GetOrMakeEntry(name, eStringType, foundEntry);
00248   if (!foundEntry)
00249     return NS_ERROR_OUT_OF_MEMORY;
00250   foundEntry->mData.mCString = new nsCString(value);
00251   return NS_OK;
00252 }
00253 
00254 /* void setISupportsValue (in AString name, in nsISupports value); */
00255 NS_IMETHODIMP nsCommandParams::SetISupportsValue(const char * name, nsISupports *value)
00256 {
00257   HashEntry*  foundEntry;
00258   GetOrMakeEntry(name, eISupportsType, foundEntry);
00259   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00260   
00261   foundEntry->mISupports = value;   // addrefs
00262   return NS_OK;
00263 }
00264 
00265 /* void removeValue (in AString name); */
00266 NS_IMETHODIMP
00267 nsCommandParams::RemoveValue(const char * name)
00268 {
00269   // PL_DHASH_REMOVE doesn't tell us if the entry was really removed, so we return
00270   // NS_OK unconditionally.
00271   (void)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_REMOVE);
00272 
00273   // inval the number of entries
00274   mNumEntries = eNumEntriesUnknown;
00275   return NS_OK;
00276 }
00277 
00278 #if 0
00279 #pragma mark -
00280 #endif
00281 
00282 nsCommandParams::HashEntry*
00283 nsCommandParams::GetNamedEntry(const char * name)
00284 {
00285   HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP);
00286 
00287   if (PL_DHASH_ENTRY_IS_BUSY(foundEntry))
00288     return foundEntry;
00289    
00290   return nsnull;
00291 }
00292 
00293 
00294 nsCommandParams::HashEntry*
00295 nsCommandParams::GetIndexedEntry(PRInt32 index)
00296 {
00297   HashEntry*  entry = NS_REINTERPRET_CAST(HashEntry*, mValuesHash.entryStore);
00298   HashEntry*  limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash);
00299   PRUint32    entryCount = 0;
00300   
00301   do
00302   {  
00303     if (!PL_DHASH_ENTRY_IS_LIVE(entry))
00304       continue;
00305 
00306     if ((PRInt32)entryCount == index)
00307       return entry;
00308     
00309     entryCount ++;
00310   } while (++entry < limit);
00311 
00312   return nsnull;
00313 }
00314 
00315 
00316 PRUint32
00317 nsCommandParams::GetNumEntries()
00318 {
00319   HashEntry*  entry = NS_REINTERPRET_CAST(HashEntry*, mValuesHash.entryStore);
00320   HashEntry*  limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash);
00321   PRUint32    entryCount = 0;
00322   
00323   do
00324   {  
00325     if (PL_DHASH_ENTRY_IS_LIVE(entry))
00326       entryCount ++;
00327   } while (++entry < limit);
00328 
00329   return entryCount;
00330 }
00331 
00332 nsresult
00333 nsCommandParams::GetOrMakeEntry(const char * name, PRUint8 entryType, HashEntry*& outEntry)
00334 {
00335 
00336   HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP);
00337   if (PL_DHASH_ENTRY_IS_BUSY(foundEntry))   // reuse existing entry  
00338   {
00339     foundEntry->Reset(entryType);
00340     foundEntry->mEntryName.Assign(name);
00341     outEntry = foundEntry;
00342     return NS_OK;
00343   }
00344 
00345   foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_ADD);
00346   if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY;
00347   
00348   // placement new that sucker. Our ctor does not clobber keyHash, which is important.
00349   outEntry = new (foundEntry) HashEntry(entryType, name);  
00350   return NS_OK;
00351 }
00352 
00353 #if 0
00354 #pragma mark -
00355 #endif
00356 
00357 const void *
00358 nsCommandParams::HashGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
00359 {
00360   HashEntry*    thisEntry = NS_STATIC_CAST(HashEntry*, entry);
00361   return (void *)thisEntry->mEntryName.get();
00362 }
00363 
00364 
00365 PLDHashNumber
00366 nsCommandParams::HashKey(PLDHashTable *table, const void *key)
00367 {
00368   return nsCRT::HashCode((const char *)key);
00369 }
00370 
00371 PRBool
00372 nsCommandParams::HashMatchEntry(PLDHashTable *table,
00373                                 const PLDHashEntryHdr *entry, const void *key)
00374 {
00375   const char*   keyString = (const char*)key;
00376   const HashEntry*   thisEntry = NS_STATIC_CAST(const HashEntry*, entry);
00377   
00378   return thisEntry->mEntryName.Equals(keyString);
00379 }
00380 
00381 void
00382 nsCommandParams::HashMoveEntry(PLDHashTable *table, const PLDHashEntryHdr *from,
00383                                 PLDHashEntryHdr *to)
00384 {
00385   const HashEntry*   fromEntry  = NS_STATIC_CAST(const HashEntry*, from);
00386   HashEntry*         toEntry    = NS_STATIC_CAST(HashEntry*, to);
00387   
00388   *toEntry = *fromEntry;
00389   // we leave from dirty, but that's OK
00390 }
00391 
00392 void
00393 nsCommandParams::HashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
00394 {
00395   HashEntry*    thisEntry = NS_STATIC_CAST(HashEntry*, entry);
00396   thisEntry->~HashEntry();      // call dtor explicitly
00397   memset(thisEntry, 0, sizeof(HashEntry));    // and clear out
00398 }
00399 
00400 #if 0
00401 #pragma mark -
00402 #endif
00403 
00404 /* boolean hasMoreElements (); */
00405 NS_IMETHODIMP
00406 nsCommandParams::HasMoreElements(PRBool *_retval)
00407 {
00408   NS_ENSURE_ARG_POINTER(_retval);
00409 
00410   if (mNumEntries == eNumEntriesUnknown)
00411     mNumEntries = GetNumEntries();
00412   
00413   *_retval = mCurEntry < mNumEntries;
00414   return NS_OK;
00415 }
00416 
00417 /* void first (); */
00418 NS_IMETHODIMP
00419 nsCommandParams::First()
00420 {
00421   mCurEntry = 0;
00422   return NS_OK;
00423 }
00424 
00425 /* AString getNext (); */
00426 NS_IMETHODIMP
00427 nsCommandParams::GetNext(char **_retval)
00428 {
00429   HashEntry*    thisEntry = GetIndexedEntry(mCurEntry);
00430   if (!thisEntry)
00431     return NS_ERROR_FAILURE;
00432   
00433   *_retval = nsCRT::strdup(thisEntry->mEntryName.get());
00434   mCurEntry++;
00435   return NS_OK;
00436 }