gecko/xpcom/ds/nsHashtable.h

369 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* This Original Code has been modified by IBM Corporation.
* Modifications made by IBM described herein are
* Copyright (c) International Business Machines
* Corporation, 2000
*
* Modifications to Mozilla code or documentation
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
*/
/**
* nsHashtable is OBSOLETE. Use nsTHashtable or a derivative instead.
*/
#ifndef nsHashtable_h__
#define nsHashtable_h__
#include "pldhash.h"
#include "nscore.h"
#include "nsISupports.h"
#include "nsTraceRefcnt.h"
#include "nsStringFwd.h"
class nsIObjectInputStream;
class nsIObjectOutputStream;
struct PRLock;
class nsHashKey {
protected:
nsHashKey(void) {
#ifdef DEBUG
mKeyType = UnknownKey;
#endif
MOZ_COUNT_CTOR(nsHashKey);
}
public:
// Virtual destructor because all hash keys are |delete|d via a
// nsHashKey pointer.
virtual ~nsHashKey(void);
virtual uint32_t HashCode(void) const = 0;
virtual bool Equals(const nsHashKey *aKey) const = 0;
virtual nsHashKey *Clone() const = 0;
virtual nsresult Write(nsIObjectOutputStream* aStream) const;
#ifdef DEBUG
public:
// used for verification that we're casting to the correct key type
enum nsHashKeyType {
UnknownKey,
SupportsKey,
PRUint32Key,
VoidKey,
IDKey,
CStringKey,
StringKey
};
nsHashKeyType GetKeyType() const { return mKeyType; }
protected:
nsHashKeyType mKeyType;
#endif
};
// Enumerator and Read/Write callback functions.
// Return values for nsHashtableEnumFunc
enum {
kHashEnumerateStop = false,
kHashEnumerateNext = true
};
typedef bool
(* nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
typedef nsresult
(* nsHashtableReadEntryFunc)(nsIObjectInputStream *aStream, nsHashKey **aKey,
void **aData);
// NB: may be called with null aKey or aData, to free just one of the two.
typedef void
(* nsHashtableFreeEntryFunc)(nsIObjectInputStream *aStream, nsHashKey *aKey,
void *aData);
typedef nsresult
(* nsHashtableWriteDataFunc)(nsIObjectOutputStream *aStream, void *aData);
class nsHashtable {
protected:
// members
PRLock* mLock;
PLDHashTable mHashtable;
bool mEnumerating;
public:
nsHashtable(uint32_t aSize = 16, bool threadSafe = false);
virtual ~nsHashtable();
int32_t Count(void) { return mHashtable.entryCount; }
bool Exists(nsHashKey *aKey);
void *Put(nsHashKey *aKey, void *aData);
void *Get(nsHashKey *aKey);
void *Remove(nsHashKey *aKey);
nsHashtable *Clone();
void Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure = nullptr);
void Reset();
void Reset(nsHashtableEnumFunc destroyFunc, void* aClosure = nullptr);
nsHashtable(nsIObjectInputStream* aStream,
nsHashtableReadEntryFunc aReadEntryFunc,
nsHashtableFreeEntryFunc aFreeEntryFunc,
nsresult *aRetVal);
nsresult Write(nsIObjectOutputStream* aStream,
nsHashtableWriteDataFunc aWriteDataFunc) const;
};
////////////////////////////////////////////////////////////////////////////////
// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
// deleted
typedef void* (* nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* aClosure);
class nsObjectHashtable : public nsHashtable {
public:
nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
void* cloneElementClosure,
nsHashtableEnumFunc destroyElementFun,
void* destroyElementClosure,
uint32_t aSize = 16, bool threadSafe = false);
~nsObjectHashtable();
nsHashtable *Clone();
void Reset();
bool RemoveAndDelete(nsHashKey *aKey);
protected:
static PLDHashOperator CopyElement(PLDHashTable* table,
PLDHashEntryHdr* hdr,
uint32_t i, void *arg);
nsHashtableCloneElementFunc mCloneElementFun;
void* mCloneElementClosure;
nsHashtableEnumFunc mDestroyElementFun;
void* mDestroyElementClosure;
};
////////////////////////////////////////////////////////////////////////////////
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
class nsSupportsHashtable
: private nsHashtable
{
public:
nsSupportsHashtable(uint32_t aSize = 16, bool threadSafe = false)
: nsHashtable(aSize, threadSafe) {}
~nsSupportsHashtable();
int32_t Count(void) {
return nsHashtable::Count();
}
bool Exists(nsHashKey *aKey) {
return nsHashtable::Exists (aKey);
}
bool Put(nsHashKey *aKey,
nsISupports *aData,
nsISupports **value = nullptr);
nsISupports* Get(nsHashKey *aKey);
bool Remove(nsHashKey *aKey, nsISupports **value = nullptr);
nsHashtable *Clone();
void Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure = nullptr) {
nsHashtable::Enumerate(aEnumFunc, aClosure);
}
void Reset();
private:
static bool ReleaseElement(nsHashKey *, void *, void *);
static PLDHashOperator EnumerateCopy(PLDHashTable*,
PLDHashEntryHdr* hdr,
uint32_t i, void *arg);
};
////////////////////////////////////////////////////////////////////////////////
// nsISupportsKey: Where keys are nsISupports objects that get refcounted.
class nsISupportsKey : public nsHashKey {
protected:
nsISupports* mKey;
public:
nsISupportsKey(const nsISupportsKey& aKey) : mKey(aKey.mKey) {
#ifdef DEBUG
mKeyType = SupportsKey;
#endif
NS_IF_ADDREF(mKey);
}
nsISupportsKey(nsISupports* key) {
#ifdef DEBUG
mKeyType = SupportsKey;
#endif
mKey = key;
NS_IF_ADDREF(mKey);
}
~nsISupportsKey(void) {
NS_IF_RELEASE(mKey);
}
uint32_t HashCode(void) const {
return NS_PTR_TO_INT32(mKey);
}
bool Equals(const nsHashKey *aKey) const {
NS_ASSERTION(aKey->GetKeyType() == SupportsKey, "mismatched key types");
return (mKey == ((nsISupportsKey *) aKey)->mKey);
}
nsHashKey *Clone() const {
return new nsISupportsKey(mKey);
}
nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult);
nsresult Write(nsIObjectOutputStream* aStream) const;
nsISupports* GetValue() { return mKey; }
};
class nsPRUint32Key : public nsHashKey {
protected:
uint32_t mKey;
public:
nsPRUint32Key(uint32_t key) {
#ifdef DEBUG
mKeyType = PRUint32Key;
#endif
mKey = key;
}
uint32_t HashCode(void) const {
return mKey;
}
bool Equals(const nsHashKey *aKey) const {
return mKey == ((const nsPRUint32Key *) aKey)->mKey;
}
nsHashKey *Clone() const {
return new nsPRUint32Key(mKey);
}
uint32_t GetValue() { return mKey; }
};
////////////////////////////////////////////////////////////////////////////////
// nsVoidKey: Where keys are void* objects that don't get refcounted.
class nsVoidKey : public nsHashKey {
protected:
void* mKey;
public:
nsVoidKey(const nsVoidKey& aKey) : mKey(aKey.mKey) {
#ifdef DEBUG
mKeyType = aKey.mKeyType;
#endif
}
nsVoidKey(void* key) {
#ifdef DEBUG
mKeyType = VoidKey;
#endif
mKey = key;
}
uint32_t HashCode(void) const {
return NS_PTR_TO_INT32(mKey);
}
bool Equals(const nsHashKey *aKey) const {
NS_ASSERTION(aKey->GetKeyType() == VoidKey, "mismatched key types");
return (mKey == ((const nsVoidKey *) aKey)->mKey);
}
nsHashKey *Clone() const {
return new nsVoidKey(mKey);
}
void* GetValue() { return mKey; }
};
// for null-terminated c-strings
class nsCStringKey : public nsHashKey {
public:
// NB: when serializing, NEVER_OWN keys are deserialized as OWN.
enum Ownership {
NEVER_OWN, // very long lived, even clones don't need to copy it.
OWN_CLONE, // as long lived as this key. But clones make a copy.
OWN // to be free'd in key dtor. Clones make their own copy.
};
nsCStringKey(const nsCStringKey& aStrKey);
nsCStringKey(const char* str, int32_t strLen = -1, Ownership own = OWN_CLONE);
nsCStringKey(const nsAFlatCString& str);
nsCStringKey(const nsACString& str);
~nsCStringKey(void);
uint32_t HashCode(void) const;
bool Equals(const nsHashKey* aKey) const;
nsHashKey* Clone() const;
nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
nsresult Write(nsIObjectOutputStream* aStream) const;
// For when the owner of the hashtable wants to peek at the actual
// string in the key. No copy is made, so be careful.
const char* GetString() const { return mStr; }
uint32_t GetStringLength() const { return mStrLen; }
protected:
char* mStr;
uint32_t mStrLen;
Ownership mOwnership;
};
// for null-terminated unicode strings
class nsStringKey : public nsHashKey {
public:
// NB: when serializing, NEVER_OWN keys are deserialized as OWN.
enum Ownership {
NEVER_OWN, // very long lived, even clones don't need to copy it.
OWN_CLONE, // as long lived as this key. But clones make a copy.
OWN // to be free'd in key dtor. Clones make their own copy.
};
nsStringKey(const nsStringKey& aKey);
nsStringKey(const PRUnichar* str, int32_t strLen = -1, Ownership own = OWN_CLONE);
nsStringKey(const nsAFlatString& str);
nsStringKey(const nsAString& str);
~nsStringKey(void);
uint32_t HashCode(void) const;
bool Equals(const nsHashKey* aKey) const;
nsHashKey* Clone() const;
nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
nsresult Write(nsIObjectOutputStream* aStream) const;
// For when the owner of the hashtable wants to peek at the actual
// string in the key. No copy is made, so be careful.
const PRUnichar* GetString() const { return mStr; }
uint32_t GetStringLength() const { return mStrLen; }
protected:
PRUnichar* mStr;
uint32_t mStrLen;
Ownership mOwnership;
};
////////////////////////////////////////////////////////////////////////////////
#endif // nsHashtable_h__