1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/embedding/components/commandhandler/src/nsCommandParams.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,396 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "xpcom-config.h" 1.10 +#include <new> // for placement new 1.11 +#include "nscore.h" 1.12 +#include "nsCRT.h" 1.13 + 1.14 +#include "nsCommandParams.h" 1.15 +#include "mozilla/HashFunctions.h" 1.16 + 1.17 +using namespace mozilla; 1.18 + 1.19 +const PLDHashTableOps nsCommandParams::sHashOps = 1.20 +{ 1.21 + PL_DHashAllocTable, 1.22 + PL_DHashFreeTable, 1.23 + HashKey, 1.24 + HashMatchEntry, 1.25 + HashMoveEntry, 1.26 + HashClearEntry, 1.27 + PL_DHashFinalizeStub 1.28 +}; 1.29 + 1.30 + 1.31 +NS_IMPL_ISUPPORTS(nsCommandParams, nsICommandParams) 1.32 + 1.33 +nsCommandParams::nsCommandParams() 1.34 +: mCurEntry(0) 1.35 +, mNumEntries(eNumEntriesUnknown) 1.36 +{ 1.37 + // init the hash table later 1.38 +} 1.39 + 1.40 +nsCommandParams::~nsCommandParams() 1.41 +{ 1.42 + PL_DHashTableFinish(&mValuesHash); 1.43 +} 1.44 + 1.45 +nsresult 1.46 +nsCommandParams::Init() 1.47 +{ 1.48 + PL_DHashTableInit(&mValuesHash, &sHashOps, (void *)this, sizeof(HashEntry), 4); 1.49 + 1.50 + return NS_OK; 1.51 +} 1.52 + 1.53 +#if 0 1.54 +#pragma mark - 1.55 +#endif 1.56 + 1.57 +/* short getValueType (in string name); */ 1.58 +NS_IMETHODIMP nsCommandParams::GetValueType(const char * name, int16_t *_retval) 1.59 +{ 1.60 + NS_ENSURE_ARG_POINTER(_retval); 1.61 + *_retval = eNoType; 1.62 + HashEntry* foundEntry = GetNamedEntry(name); 1.63 + if (foundEntry) 1.64 + { 1.65 + *_retval = foundEntry->mEntryType; 1.66 + return NS_OK; 1.67 + } 1.68 + 1.69 + return NS_ERROR_FAILURE; 1.70 +} 1.71 + 1.72 +/* boolean getBooleanValue (in AString name); */ 1.73 +NS_IMETHODIMP nsCommandParams::GetBooleanValue(const char * name, bool *_retval) 1.74 +{ 1.75 + NS_ENSURE_ARG_POINTER(_retval); 1.76 + *_retval = false; 1.77 + 1.78 + HashEntry* foundEntry = GetNamedEntry(name); 1.79 + if (foundEntry && foundEntry->mEntryType == eBooleanType) 1.80 + { 1.81 + *_retval = foundEntry->mData.mBoolean; 1.82 + return NS_OK; 1.83 + } 1.84 + 1.85 + return NS_ERROR_FAILURE; 1.86 +} 1.87 + 1.88 +/* long getLongValue (in AString name); */ 1.89 +NS_IMETHODIMP nsCommandParams::GetLongValue(const char * name, int32_t *_retval) 1.90 +{ 1.91 + NS_ENSURE_ARG_POINTER(_retval); 1.92 + *_retval = false; 1.93 + 1.94 + HashEntry* foundEntry = GetNamedEntry(name); 1.95 + if (foundEntry && foundEntry->mEntryType == eLongType) 1.96 + { 1.97 + *_retval = foundEntry->mData.mLong; 1.98 + return NS_OK; 1.99 + } 1.100 + 1.101 + return NS_ERROR_FAILURE; 1.102 +} 1.103 + 1.104 +/* double getDoubleValue (in AString name); */ 1.105 +NS_IMETHODIMP nsCommandParams::GetDoubleValue(const char * name, double *_retval) 1.106 +{ 1.107 + NS_ENSURE_ARG_POINTER(_retval); 1.108 + *_retval = 0.0; 1.109 + 1.110 + HashEntry* foundEntry = GetNamedEntry(name); 1.111 + if (foundEntry && foundEntry->mEntryType == eDoubleType) 1.112 + { 1.113 + *_retval = foundEntry->mData.mDouble; 1.114 + return NS_OK; 1.115 + } 1.116 + 1.117 + return NS_ERROR_FAILURE; 1.118 +} 1.119 + 1.120 +/* AString getStringValue (in AString name); */ 1.121 +NS_IMETHODIMP nsCommandParams::GetStringValue(const char *name, nsAString & _retval) 1.122 +{ 1.123 + _retval.Truncate(); 1.124 + HashEntry* foundEntry = GetNamedEntry(name); 1.125 + if (foundEntry && foundEntry->mEntryType == eWStringType) 1.126 + { 1.127 + NS_ASSERTION(foundEntry->mData.mString, "Null string"); 1.128 + _retval.Assign(*foundEntry->mData.mString); 1.129 + return NS_OK; 1.130 + } 1.131 + 1.132 + return NS_ERROR_FAILURE; 1.133 +} 1.134 + 1.135 +/* AString getStringValue (in AString name); */ 1.136 +NS_IMETHODIMP nsCommandParams::GetCStringValue(const char * name, char **_retval) 1.137 +{ 1.138 + HashEntry* foundEntry = GetNamedEntry(name); 1.139 + if (foundEntry && foundEntry->mEntryType == eStringType) 1.140 + { 1.141 + NS_ASSERTION(foundEntry->mData.mCString, "Null string"); 1.142 + *_retval = ToNewCString(*foundEntry->mData.mCString); 1.143 + return NS_OK; 1.144 + } 1.145 + 1.146 + return NS_ERROR_FAILURE; 1.147 +} 1.148 + 1.149 +/* nsISupports getISupportsValue (in AString name); */ 1.150 +NS_IMETHODIMP nsCommandParams::GetISupportsValue(const char * name, nsISupports **_retval) 1.151 +{ 1.152 + NS_ENSURE_ARG_POINTER(_retval); 1.153 + *_retval = nullptr; 1.154 + 1.155 + HashEntry* foundEntry = GetNamedEntry(name); 1.156 + if (foundEntry && foundEntry->mEntryType == eISupportsType) 1.157 + { 1.158 + NS_IF_ADDREF(*_retval = foundEntry->mISupports.get()); 1.159 + return NS_OK; 1.160 + } 1.161 + 1.162 + return NS_ERROR_FAILURE; 1.163 +} 1.164 + 1.165 +#if 0 1.166 +#pragma mark - 1.167 +#endif 1.168 + 1.169 +/* void setBooleanValue (in AString name, in boolean value); */ 1.170 +NS_IMETHODIMP nsCommandParams::SetBooleanValue(const char * name, bool value) 1.171 +{ 1.172 + HashEntry* foundEntry; 1.173 + GetOrMakeEntry(name, eBooleanType, foundEntry); 1.174 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.175 + 1.176 + foundEntry->mData.mBoolean = value; 1.177 + 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 +/* void setLongValue (in AString name, in long value); */ 1.182 +NS_IMETHODIMP nsCommandParams::SetLongValue(const char * name, int32_t value) 1.183 +{ 1.184 + HashEntry* foundEntry; 1.185 + GetOrMakeEntry(name, eLongType, foundEntry); 1.186 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.187 + 1.188 + foundEntry->mData.mLong = value; 1.189 + return NS_OK; 1.190 +} 1.191 + 1.192 +/* void setDoubleValue (in AString name, in double value); */ 1.193 +NS_IMETHODIMP nsCommandParams::SetDoubleValue(const char * name, double value) 1.194 +{ 1.195 + HashEntry* foundEntry; 1.196 + GetOrMakeEntry(name, eDoubleType, foundEntry); 1.197 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.198 + 1.199 + foundEntry->mData.mDouble = value; 1.200 + return NS_OK; 1.201 +} 1.202 + 1.203 +/* void setStringValue (in AString name, in AString value); */ 1.204 +NS_IMETHODIMP nsCommandParams::SetStringValue(const char * name, const nsAString & value) 1.205 +{ 1.206 + HashEntry* foundEntry; 1.207 + GetOrMakeEntry(name, eWStringType, foundEntry); 1.208 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.209 + 1.210 + foundEntry->mData.mString = new nsString(value); 1.211 + return NS_OK; 1.212 +} 1.213 + 1.214 +/* void setCStringValue (in string name, in string value); */ 1.215 +NS_IMETHODIMP nsCommandParams::SetCStringValue(const char * name, const char * value) 1.216 +{ 1.217 + HashEntry* foundEntry; 1.218 + GetOrMakeEntry(name, eStringType, foundEntry); 1.219 + if (!foundEntry) 1.220 + return NS_ERROR_OUT_OF_MEMORY; 1.221 + foundEntry->mData.mCString = new nsCString(value); 1.222 + return NS_OK; 1.223 +} 1.224 + 1.225 +/* void setISupportsValue (in AString name, in nsISupports value); */ 1.226 +NS_IMETHODIMP nsCommandParams::SetISupportsValue(const char * name, nsISupports *value) 1.227 +{ 1.228 + HashEntry* foundEntry; 1.229 + GetOrMakeEntry(name, eISupportsType, foundEntry); 1.230 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.231 + 1.232 + foundEntry->mISupports = value; // addrefs 1.233 + return NS_OK; 1.234 +} 1.235 + 1.236 +/* void removeValue (in AString name); */ 1.237 +NS_IMETHODIMP 1.238 +nsCommandParams::RemoveValue(const char * name) 1.239 +{ 1.240 + // PL_DHASH_REMOVE doesn't tell us if the entry was really removed, so we return 1.241 + // NS_OK unconditionally. 1.242 + (void)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_REMOVE); 1.243 + 1.244 + // inval the number of entries 1.245 + mNumEntries = eNumEntriesUnknown; 1.246 + return NS_OK; 1.247 +} 1.248 + 1.249 +#if 0 1.250 +#pragma mark - 1.251 +#endif 1.252 + 1.253 +nsCommandParams::HashEntry* 1.254 +nsCommandParams::GetNamedEntry(const char * name) 1.255 +{ 1.256 + HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP); 1.257 + 1.258 + if (PL_DHASH_ENTRY_IS_BUSY(foundEntry)) 1.259 + return foundEntry; 1.260 + 1.261 + return nullptr; 1.262 +} 1.263 + 1.264 + 1.265 +nsCommandParams::HashEntry* 1.266 +nsCommandParams::GetIndexedEntry(int32_t index) 1.267 +{ 1.268 + HashEntry* entry = reinterpret_cast<HashEntry*>(mValuesHash.entryStore); 1.269 + HashEntry* limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash); 1.270 + uint32_t entryCount = 0; 1.271 + 1.272 + do 1.273 + { 1.274 + if (!PL_DHASH_ENTRY_IS_LIVE(entry)) 1.275 + continue; 1.276 + 1.277 + if ((int32_t)entryCount == index) 1.278 + return entry; 1.279 + 1.280 + entryCount ++; 1.281 + } while (++entry < limit); 1.282 + 1.283 + return nullptr; 1.284 +} 1.285 + 1.286 + 1.287 +uint32_t 1.288 +nsCommandParams::GetNumEntries() 1.289 +{ 1.290 + HashEntry* entry = reinterpret_cast<HashEntry*>(mValuesHash.entryStore); 1.291 + HashEntry* limit = entry + PL_DHASH_TABLE_SIZE(&mValuesHash); 1.292 + uint32_t entryCount = 0; 1.293 + 1.294 + do 1.295 + { 1.296 + if (PL_DHASH_ENTRY_IS_LIVE(entry)) 1.297 + entryCount ++; 1.298 + } while (++entry < limit); 1.299 + 1.300 + return entryCount; 1.301 +} 1.302 + 1.303 +nsresult 1.304 +nsCommandParams::GetOrMakeEntry(const char * name, uint8_t entryType, HashEntry*& outEntry) 1.305 +{ 1.306 + 1.307 + HashEntry *foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_LOOKUP); 1.308 + if (PL_DHASH_ENTRY_IS_BUSY(foundEntry)) // reuse existing entry 1.309 + { 1.310 + foundEntry->Reset(entryType); 1.311 + foundEntry->mEntryName.Assign(name); 1.312 + outEntry = foundEntry; 1.313 + return NS_OK; 1.314 + } 1.315 + 1.316 + foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)name, PL_DHASH_ADD); 1.317 + if (!foundEntry) return NS_ERROR_OUT_OF_MEMORY; 1.318 + 1.319 + // placement new that sucker. Our ctor does not clobber keyHash, which is important. 1.320 + outEntry = new (foundEntry) HashEntry(entryType, name); 1.321 + return NS_OK; 1.322 +} 1.323 + 1.324 +#if 0 1.325 +#pragma mark - 1.326 +#endif 1.327 + 1.328 +PLDHashNumber 1.329 +nsCommandParams::HashKey(PLDHashTable *table, const void *key) 1.330 +{ 1.331 + return HashString((const char *)key); 1.332 +} 1.333 + 1.334 +bool 1.335 +nsCommandParams::HashMatchEntry(PLDHashTable *table, 1.336 + const PLDHashEntryHdr *entry, const void *key) 1.337 +{ 1.338 + const char* keyString = (const char*)key; 1.339 + const HashEntry* thisEntry = static_cast<const HashEntry*>(entry); 1.340 + 1.341 + return thisEntry->mEntryName.Equals(keyString); 1.342 +} 1.343 + 1.344 +void 1.345 +nsCommandParams::HashMoveEntry(PLDHashTable *table, const PLDHashEntryHdr *from, 1.346 + PLDHashEntryHdr *to) 1.347 +{ 1.348 + const HashEntry* fromEntry = static_cast<const HashEntry*>(from); 1.349 + HashEntry* toEntry = static_cast<HashEntry*>(to); 1.350 + 1.351 + *toEntry = *fromEntry; 1.352 + // we leave from dirty, but that's OK 1.353 +} 1.354 + 1.355 +void 1.356 +nsCommandParams::HashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) 1.357 +{ 1.358 + HashEntry* thisEntry = static_cast<HashEntry*>(entry); 1.359 + thisEntry->~HashEntry(); // call dtor explicitly 1.360 + memset(thisEntry, 0, sizeof(HashEntry)); // and clear out 1.361 +} 1.362 + 1.363 +#if 0 1.364 +#pragma mark - 1.365 +#endif 1.366 + 1.367 +/* boolean hasMoreElements (); */ 1.368 +NS_IMETHODIMP 1.369 +nsCommandParams::HasMoreElements(bool *_retval) 1.370 +{ 1.371 + NS_ENSURE_ARG_POINTER(_retval); 1.372 + 1.373 + if (mNumEntries == eNumEntriesUnknown) 1.374 + mNumEntries = GetNumEntries(); 1.375 + 1.376 + *_retval = mCurEntry < mNumEntries; 1.377 + return NS_OK; 1.378 +} 1.379 + 1.380 +/* void first (); */ 1.381 +NS_IMETHODIMP 1.382 +nsCommandParams::First() 1.383 +{ 1.384 + mCurEntry = 0; 1.385 + return NS_OK; 1.386 +} 1.387 + 1.388 +/* AString getNext (); */ 1.389 +NS_IMETHODIMP 1.390 +nsCommandParams::GetNext(char **_retval) 1.391 +{ 1.392 + HashEntry* thisEntry = GetIndexedEntry(mCurEntry); 1.393 + if (!thisEntry) 1.394 + return NS_ERROR_FAILURE; 1.395 + 1.396 + *_retval = ToNewCString(thisEntry->mEntryName); 1.397 + mCurEntry++; 1.398 + return NS_OK; 1.399 +}