summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/ds
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/libs/xpcom18a4/xpcom/ds
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/Makefile.in171
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArray.cpp226
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArray.h118
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp210
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h87
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomService.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp616
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h101
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h127
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h458
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp170
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp162
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h267
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp534
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCRT.h301
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp180
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h194
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h149
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h127
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h62
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp627
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDeque.h405
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h505
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp108
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h64
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp253
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h201
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h315
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp46
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashSets.h107
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp896
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashtable.h454
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIArray.idl202
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl161
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl73
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h95
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsICollection.idl92
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl89
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl58
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl111
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h8
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl79
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl77
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl68
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl81
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl58
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl139
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl325
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl304
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl242
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h73
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl188
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsInt64.h399
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h121
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp211
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverList.h79
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp227
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverService.h75
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp492
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h106
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp150
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsProperties.h72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp182
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp443
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h208
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h197
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp217
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h81
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h122
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp684
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h172
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp148
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp880
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h358
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h429
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp1557
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h115
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTime.h143
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp613
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h64
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp141
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h207
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp304
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsValueArray.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp2092
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVariant.h203
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp1560
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h410
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/pldhash.c826
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/pldhash.h603
105 files changed, 27285 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/ds/.cvsignore b/src/libs/xpcom18a4/xpcom/ds/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/ds/Makefile.in b/src/libs/xpcom18a4/xpcom/ds/Makefile.in
new file mode 100644
index 00000000..8da8853c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/Makefile.in
@@ -0,0 +1,171 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_ds
+LIBRARY_NAME = xpcomds_s
+GRE_MODULE = 1
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+CSRCS = \
+ pldhash.c \
+ $(NULL)
+
+CPPSRCS = \
+ nsAtomTable.cpp \
+ nsAtomService.cpp \
+ nsByteBuffer.cpp \
+ nsCheapSets.cpp \
+ nsCRT.cpp \
+ nsDeque.cpp \
+ nsEmptyEnumerator.cpp \
+ nsEnumeratorUtils.cpp \
+ nsFixedSizeAllocator.cpp \
+ nsHashSets.cpp \
+ nsHashtable.cpp \
+ nsObserverList.cpp \
+ nsObserverService.cpp \
+ nsProperties.cpp \
+ nsPersistentProperties.cpp \
+ nsQuickSort.cpp \
+ nsRecyclingAllocator.cpp \
+ nsStaticNameTable.cpp \
+ nsStringEnumerator.cpp \
+ nsSupportsArray.cpp \
+ nsSupportsArrayEnumerator.cpp \
+ nsSupportsPrimitives.cpp \
+ nsTHashtable.cpp \
+ nsUnicharBuffer.cpp \
+ nsVariant.cpp \
+ nsVoidArray.cpp \
+ nsTextFormatter.cpp \
+ nsTimelineService.cpp \
+ nsValueArray.cpp \
+ nsCOMArray.cpp \
+ nsArray.cpp \
+ nsArrayEnumerator.cpp \
+ $(NULL)
+
+EXPORTS = \
+ nsAtomService.h \
+ nsBaseHashtable.h \
+ nsCheapSets.h \
+ nsClassHashtable.h \
+ nsCppSharedAllocator.h \
+ nsCRT.h \
+ nsDataHashtable.h \
+ nsDeque.h \
+ nsDoubleHashtable.h \
+ nsEnumeratorUtils.h \
+ nsFixedSizeAllocator.h \
+ nsHashSets.h \
+ nsHashKeys.h \
+ nsHashtable.h \
+ nsIByteBuffer.h \
+ nsIUnicharBuffer.h \
+ nsInt64.h \
+ nsInterfaceHashtable.h \
+ nsObserverService.h \
+ nsQuickSort.h \
+ nsRecyclingAllocator.h \
+ nsRefPtrHashtable.h \
+ nsStaticNameTable.h \
+ nsStaticAtom.h \
+ nsSupportsArray.h \
+ nsSupportsPrimitives.h \
+ nsTHashtable.h \
+ nsTime.h \
+ nsUnitConversion.h \
+ nsVariant.h \
+ nsVoidArray.h \
+ pldhash.h \
+ nsTextFormatter.h \
+ nsValueArray.h \
+ nsArray.h \
+ nsArrayEnumerator.h \
+ nsCOMArray.h \
+ nsStringEnumerator.h \
+ nsAutoBuffer.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIAtom.idl \
+ nsIAtomService.idl \
+ nsICollection.idl \
+ nsIEnumerator.idl \
+ nsIPersistentProperties2.idl \
+ nsIPropertyBag.idl \
+ nsIRecyclingAllocator.idl \
+ nsIVariant.idl \
+ nsISerializable.idl \
+ nsIStringEnumerator.idl \
+ nsISupportsArray.idl \
+ nsISupportsIterators.idl \
+ nsITimelineService.idl \
+ nsIArray.idl \
+ $(NULL)
+
+SDK_XPIDLSRCS = \
+ nsIObserverService.idl \
+ nsIObserver.idl \
+ nsIProperties.idl \
+ nsISimpleEnumerator.idl \
+ nsISupportsPrimitives.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+
+DEFINES += -D_IMPL_NS_COM
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp
new file mode 100644
index 00000000..9eaf7868
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp
@@ -0,0 +1,226 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsArray.h"
+#include "nsArrayEnumerator.h"
+#include "nsWeakReference.h"
+
+// used by IndexOf()
+struct findIndexOfClosure
+{
+ nsISupports *targetElement;
+ PRUint32 startIndex;
+ PRUint32 resultIndex;
+};
+
+PR_STATIC_CALLBACK(PRBool) FindElementCallback(void* aElement, void* aClosure);
+
+
+NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray)
+
+nsArray::~nsArray()
+{
+ Clear();
+}
+
+NS_IMETHODIMP
+nsArray::GetLength(PRUint32* aLength)
+{
+ *aLength = mArray.Count();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArray::QueryElementAt(PRUint32 aIndex,
+ const nsIID& aIID,
+ void ** aResult)
+{
+ nsISupports * obj = mArray.ObjectAt(aIndex);
+ if (!obj) return NS_ERROR_UNEXPECTED;
+
+ // no need to worry about a leak here, because ObjectAt() doesn't
+ // addref its result
+ return obj->QueryInterface(aIID, aResult);
+}
+
+NS_IMETHODIMP
+nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
+ PRUint32* aResult)
+{
+ // optimize for the common case by forwarding to mArray
+ if (aStartIndex == 0) {
+ *aResult = mArray.IndexOf(aElement);
+ if (*aResult == -1)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+ }
+
+ findIndexOfClosure closure = { aElement, aStartIndex, 0 };
+ PRBool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
+ if (notFound)
+ return NS_ERROR_FAILURE;
+
+ *aResult = closure.resultIndex;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArray::Enumerate(nsISimpleEnumerator **aResult)
+{
+ return NS_NewArrayEnumerator(aResult, NS_STATIC_CAST(nsIArray*, this));
+}
+
+// nsIMutableArray implementation
+
+NS_IMETHODIMP
+nsArray::AppendElement(nsISupports* aElement, PRBool aWeak)
+{
+ PRBool result;
+ if (aWeak) {
+ nsCOMPtr<nsISupports> elementRef =
+ getter_AddRefs(NS_STATIC_CAST(nsISupports*,
+ NS_GetWeakReference(aElement)));
+ NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it");
+ if (!elementRef)
+ return NS_ERROR_FAILURE;
+ result = mArray.AppendObject(elementRef);
+ }
+
+ else {
+ // add the object directly
+ result = mArray.AppendObject(aElement);
+ }
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::RemoveElementAt(PRUint32 aIndex)
+{
+ PRBool result = mArray.RemoveObjectAt(aIndex);
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
+{
+ nsCOMPtr<nsISupports> elementRef;
+ if (aWeak) {
+ elementRef =
+ getter_AddRefs(NS_STATIC_CAST(nsISupports*,
+ NS_GetWeakReference(aElement)));
+ NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
+ if (!elementRef)
+ return NS_ERROR_FAILURE;
+ } else {
+ elementRef = aElement;
+ }
+ PRBool result = mArray.InsertObjectAt(elementRef, aIndex);
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::Clear()
+{
+ mArray.Clear();
+ return NS_OK;
+}
+
+//
+// static helper routines
+//
+PRBool
+FindElementCallback(void *aElement, void* aClosure)
+{
+ findIndexOfClosure* closure =
+ NS_STATIC_CAST(findIndexOfClosure*, aClosure);
+
+ nsISupports* element =
+ NS_STATIC_CAST(nsISupports*, aElement);
+
+ // don't start searching until we're past the startIndex
+ if (closure->resultIndex >= closure->startIndex &&
+ element == closure->targetElement) {
+ return PR_FALSE; // stop! We found it
+ }
+ closure->resultIndex++;
+
+ return PR_TRUE;
+}
+
+//
+// do_QueryElementAt helper stuff
+//
+nsresult
+nsQueryArrayElementAt::operator()(const nsIID& aIID, void** aResult) const
+ {
+ nsresult status = mArray
+ ? mArray->QueryElementAt(mIndex, aIID, aResult)
+ : NS_ERROR_NULL_POINTER;
+
+ if (mErrorPtr)
+ *mErrorPtr = status;
+
+ return status;
+ }
+
+//
+// exported constructor routines
+//
+nsresult
+NS_NewArray(nsIMutableArray** aResult)
+{
+ nsArray* arr = new nsArray;
+ if (!arr) return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = NS_STATIC_CAST(nsIMutableArray*,arr);
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+}
+
+nsresult
+NS_NewArray(nsIMutableArray** aResult, const nsCOMArray_base& aBaseArray)
+{
+ nsArray* arr = new nsArray(aBaseArray);
+ if (!arr) return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = NS_STATIC_CAST(nsIMutableArray*, arr);
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArray.h b/src/libs/xpcom18a4/xpcom/ds/nsArray.h
new file mode 100644
index 00000000..4a4f6cf2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArray.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsArray_h__
+#define nsArray_h__
+
+#include "nsIArray.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+
+#define NS_ARRAY_CLASSNAME \
+ "nsIArray implementation"
+
+// {35C66FD1-95E9-4e0a-80C5-C3BD2B375481}
+#define NS_ARRAY_CID \
+{ 0x35c66fd1, 0x95e9, 0x4e0a, \
+ { 0x80, 0xc5, 0xc3, 0xbd, 0x2b, 0x37, 0x54, 0x81 } }
+
+
+// create a new, empty array
+nsresult NS_COM
+NS_NewArray(nsIMutableArray** aResult);
+
+// The resulting array will hold an owning reference to every element
+// in the original nsCOMArray<T>. This also means that any further
+// changes to the original nsCOMArray<T> will not affect the new
+// array, and that the original array can go away and the new array
+// will still hold valid elements.
+nsresult NS_COM
+NS_NewArray(nsIMutableArray** aResult, const nsCOMArray_base& base);
+
+// adapter class to map nsIArray->nsCOMArray
+// do NOT declare this as a stack or member variable, use
+// nsCOMArray instead!
+// if you need to convert a nsCOMArray->nsIArray, see NS_NewArray above
+class nsArray : public nsIMutableArray
+{
+public:
+ nsArray() { }
+ nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
+ { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIARRAY
+ NS_DECL_NSIMUTABLEARRAY
+
+private:
+ ~nsArray();
+
+ nsCOMArray_base mArray;
+};
+
+
+// helper class for do_QueryElementAt
+class NS_COM nsQueryArrayElementAt : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryArrayElementAt(nsIArray* aArray, PRUint32 aIndex,
+ nsresult* aErrorPtr)
+ : mArray(aArray),
+ mIndex(aIndex),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
+
+ private:
+ nsIArray* mArray;
+ PRUint32 mIndex;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryArrayElementAt
+do_QueryElementAt(nsIArray* aArray, PRUint32 aIndex, nsresult* aErrorPtr = 0)
+ {
+ return nsQueryArrayElementAt(aArray, aIndex, aErrorPtr);
+ }
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp
new file mode 100644
index 00000000..c105622a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsArrayEnumerator.h"
+
+NS_IMPL_ISUPPORTS1(nsSimpleArrayEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsSimpleArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->GetLength(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ *aResult = (mIndex < cnt);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSimpleArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->GetLength(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mIndex >= cnt)
+ return NS_ERROR_UNEXPECTED;
+
+ return mValueArray->QueryElementAt(mIndex++, NS_GET_IID(nsISupports), (void**)aResult);
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsIArray* array)
+{
+ nsSimpleArrayEnumerator* enumer = new nsSimpleArrayEnumerator(array);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*result = enumer);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// enumerator implementation for nsCOMArray
+// creates a snapshot of the array in question
+// you MUST use NS_NewArrayEnumerator to create this, so that
+// allocation is done correctly
+class nsCOMArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ // nsSimpleArrayEnumerator methods
+ nsCOMArrayEnumerator() : mIndex(0) {
+ }
+
+ // specialized operator to make sure we make room for mValues
+ void* operator new (size_t size, const nsCOMArray_base& aArray) CPP_THROW_NEW;
+ void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+
+private:
+ ~nsCOMArrayEnumerator(void);
+
+protected:
+ PRUint32 mIndex; // current position
+ PRUint32 mArraySize; // size of the array
+
+ // this is actually bigger
+ nsISupports* mValueArray[1];
+};
+
+NS_IMPL_ISUPPORTS1(nsCOMArrayEnumerator, nsISimpleEnumerator)
+
+nsCOMArrayEnumerator::~nsCOMArrayEnumerator()
+{
+ // only release the entries that we haven't visited yet
+ for (; mIndex < mArraySize; ++mIndex) {
+ NS_IF_RELEASE(mValueArray[mIndex]);
+ }
+}
+
+NS_IMETHODIMP
+nsCOMArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ *aResult = (mIndex < mArraySize);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCOMArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mIndex >= mArraySize)
+ return NS_ERROR_UNEXPECTED;
+
+ // pass the ownership of the reference to the caller. Since
+ // we AddRef'ed during creation of |this|, there is no need
+ // to AddRef here
+ *aResult = mValueArray[mIndex++];
+
+ // this really isn't necessary. just pretend this happens, since
+ // we'll never visit this value again!
+ // mValueArray[(mIndex-1)] = nsnull;
+
+ return NS_OK;
+}
+
+void*
+nsCOMArrayEnumerator::operator new (size_t size, const nsCOMArray_base& aArray)
+ CPP_THROW_NEW
+{
+ // create enough space such that mValueArray points to a large
+ // enough value. Note that the initial value of size gives us
+ // space for mValueArray[0], so we must subtract
+ size += (aArray.Count() - 1) * sizeof(aArray[0]);
+
+ // do the actual allocation
+ nsCOMArrayEnumerator * result =
+ NS_STATIC_CAST(nsCOMArrayEnumerator*, ::operator new(size));
+
+ // now need to copy over the values, and addref each one
+ // now this might seem like alot of work, but we're actually just
+ // doing all our AddRef's ahead of time since GetNext() doesn't
+ // need to AddRef() on the way out
+ PRUint32 i;
+ PRUint32 max = result->mArraySize = aArray.Count();
+ for (i = 0; i<max; i++) {
+ result->mValueArray[i] = aArray[i];
+ NS_IF_ADDREF(result->mValueArray[i]);
+ }
+
+ return result;
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *aResult,
+ const nsCOMArray_base& aArray)
+{
+ nsCOMArrayEnumerator *enumerator = new (aArray) nsCOMArrayEnumerator();
+ if (!enumerator) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*aResult = enumerator);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h
new file mode 100644
index 00000000..e22302b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsArrayEnumerator_h__
+#define nsArrayEnumerator_h__
+
+// enumerator implementation for nsIArray
+
+#include "nsIArray.h"
+#include "nsCOMArray.h"
+#include "nsISimpleEnumerator.h"
+#include "nsCOMPtr.h"
+
+class nsSimpleArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ // nsSimpleArrayEnumerator methods
+ nsSimpleArrayEnumerator(nsIArray* aValueArray) :
+ mValueArray(aValueArray), mIndex(0) {
+ }
+
+private:
+ ~nsSimpleArrayEnumerator() {}
+
+protected:
+ nsCOMPtr<nsIArray> mValueArray;
+ PRUint32 mIndex;
+};
+
+
+// Create an enumerator for an existing nsIArray implementation
+// The enumerator holds an owning reference to the array.
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsIArray* array);
+
+
+// create an enumerator for an existing nsCOMArray<T> implementation
+// The enumerator will hold an owning reference to each ELEMENT in
+// the array. This means that the nsCOMArray<T> can safely go away
+// without its objects going away.
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *aResult,
+ const nsCOMArray_base& aArray);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp
new file mode 100644
index 00000000..f0366043
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAtomService.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsAtomService, nsIAtomService)
+
+nsAtomService::nsAtomService()
+{
+}
+
+nsresult
+nsAtomService::GetAtom(const PRUnichar *aString, nsIAtom ** aResult)
+{
+ *aResult = NS_NewAtom(aString);
+
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+nsresult
+nsAtomService::GetPermanentAtom(const PRUnichar *aString, nsIAtom ** aResult)
+{
+ *aResult = NS_NewPermanentAtom(aString);
+
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h
new file mode 100644
index 00000000..ae036b80
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsAtomService_h
+#define __nsAtomService_h
+
+#include "nsIAtomService.h"
+
+class nsAtomService : public nsIAtomService
+{
+ public:
+ nsAtomService();
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIATOMSERVICE
+
+ private:
+ ~nsAtomService() {}
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp
new file mode 100644
index 00000000..fc92dec8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp
@@ -0,0 +1,616 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:ts=2:et:sw=2:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAtomTable.h"
+#include "nsStaticAtom.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "pldhash.h"
+#include "prenv.h"
+#include "nsVoidArray.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "plarena.h"
+
+class nsStaticAtomWrapper;
+
+/**
+ * The shared hash table for atom lookups.
+ *
+ * XXX This should be manipulated in a threadsafe way or we should make
+ * sure it's only manipulated from the main thread. Probably the latter
+ * is better, since the former would hurt performance.
+ *
+ * If |gAtomTable.ops| is 0, then the table is uninitialized.
+ */
+static PLDHashTable gAtomTable;
+
+// this is where we keep the nsStaticAtomWrapper objects
+
+static PLArenaPool* gStaticAtomArena = 0;
+
+class nsStaticAtomWrapper : public nsIAtom
+{
+public:
+ nsStaticAtomWrapper(const nsStaticAtom* aAtom) :
+ mStaticAtom(aAtom)
+ {
+ MOZ_COUNT_CTOR(nsStaticAtomWrapper);
+ }
+ ~nsStaticAtomWrapper() { // no subclasses -> not virtual
+ // this is arena allocated and won't be called except in debug
+ // builds. If this function ever does anything non-debug, be sure
+ // to get rid of the ifdefs in AtomTableClearEntry!
+ MOZ_COUNT_DTOR(nsStaticAtomWrapper);
+ }
+
+ NS_IMETHOD QueryInterface(REFNSIID aIID,
+ void** aInstancePtr);
+ NS_IMETHOD_(nsrefcnt) AddRef(void);
+ NS_IMETHOD_(nsrefcnt) Release(void);
+
+ NS_DECL_NSIATOM
+
+ const nsStaticAtom* GetStaticAtom() {
+ return mStaticAtom;
+ }
+private:
+ const nsStaticAtom* mStaticAtom;
+};
+
+// the atomtableentry can contain either an AtomImpl or a
+// nsStaticAtomWrapper, indicated by the first bit of PtrBits
+typedef unsigned long PtrBits;
+
+struct AtomTableEntry : public PLDHashEntryHdr {
+ // mAtom & 0x1 means (mAtom & ~0x1) points to an nsStaticAtomWrapper
+ // else it points to an nsAtomImpl
+ PtrBits mAtom;
+
+ inline PRBool IsStaticAtom() const {
+ return (mAtom & 0x1) != 0;
+ }
+
+ inline void SetAtomImpl(AtomImpl* aAtom) {
+ NS_ASSERTION(aAtom, "Setting null atom");
+ mAtom = PtrBits(aAtom);
+ }
+
+ inline void SetStaticAtomWrapper(nsStaticAtomWrapper* aAtom) {
+ NS_ASSERTION(aAtom, "Setting null atom");
+ NS_ASSERTION((PtrBits(aAtom) & ~0x1) == PtrBits(aAtom),
+ "Pointers must align or this is broken");
+
+ mAtom = PtrBits(aAtom) | 0x1;
+ }
+
+ inline void ClearAtom() {
+ mAtom = nsnull;
+ }
+
+ inline PRBool HasValue() const {
+ return (mAtom & ~0x1) != 0;
+ }
+
+ // these accessors assume that you already know the type
+ inline AtomImpl *GetAtomImpl() const {
+ NS_ASSERTION(!IsStaticAtom(), "This is a static atom, not an AtomImpl");
+ return (AtomImpl*) (mAtom & ~0x1);
+ }
+
+ inline nsStaticAtomWrapper *GetStaticAtomWrapper() const {
+ NS_ASSERTION(IsStaticAtom(), "This is an AtomImpl, not a static atom");
+ return (nsStaticAtomWrapper*) (mAtom & ~0x1);
+ }
+
+ inline const nsStaticAtom* GetStaticAtom() const {
+ return GetStaticAtomWrapper()->GetStaticAtom();
+ }
+
+ // type-agnostic accessors
+
+ // get the string buffer
+ inline const char* get() const {
+ return IsStaticAtom() ? GetStaticAtom()->mString : GetAtomImpl()->mString;
+ }
+
+ // get an addreffed nsIAtom - not using already_AddRef'ed atom
+ // because the callers are not (and should not be) using nsCOMPtr
+ inline nsIAtom* GetAtom() const {
+ nsIAtom* result;
+
+ if (IsStaticAtom())
+ result = GetStaticAtomWrapper();
+ else {
+ result = GetAtomImpl();
+ NS_ADDREF(result);
+ }
+
+ return result;
+ }
+};
+
+PR_STATIC_CALLBACK(const void *)
+AtomTableGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ AtomTableEntry *he = NS_STATIC_CAST(AtomTableEntry*, entry);
+ NS_ASSERTION(he->HasValue(), "Empty atom. how did that happen?");
+ return he->get();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+AtomTableMatchKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const AtomTableEntry *he = NS_STATIC_CAST(const AtomTableEntry*, entry);
+ const char* keyStr = NS_STATIC_CAST(const char*, key);
+ return nsCRT::strcmp(keyStr, he->get()) == 0;
+}
+
+PR_STATIC_CALLBACK(void)
+AtomTableClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ AtomTableEntry *he = NS_STATIC_CAST(AtomTableEntry*, entry);
+
+ he->keyHash = 0;
+
+ if (!he->IsStaticAtom()) {
+ AtomImpl *atom = he->GetAtomImpl();
+ // Normal |AtomImpl| atoms are deleted when their refcount hits 0, and
+ // they then remove themselves from the table. In other words, they
+ // are owned by the callers who own references to them.
+ // |PermanentAtomImpl| permanent atoms ignore their refcount and are
+ // deleted when they are removed from the table at table destruction.
+ // In other words, they are owned by the atom table.
+ if (atom->IsPermanent())
+ delete NS_STATIC_CAST(PermanentAtomImpl*, atom);
+ }
+ else {
+ he->GetStaticAtomWrapper()->~nsStaticAtomWrapper();
+ }
+
+ he->ClearAtom();
+}
+
+static const PLDHashTableOps AtomTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ AtomTableGetKey,
+ PL_DHashStringKey,
+ AtomTableMatchKey,
+ PL_DHashMoveEntryStub,
+ AtomTableClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+
+#ifdef DEBUG
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+DumpAtomLeaks(PLDHashTable *table, PLDHashEntryHdr *he,
+ PRUint32 index, void *arg)
+{
+ AtomTableEntry *entry = NS_STATIC_CAST(AtomTableEntry*, he);
+
+ if (entry->IsStaticAtom())
+ return PL_DHASH_NEXT;
+
+ AtomImpl* atom = entry->GetAtomImpl();
+ if (!atom->IsPermanent()) {
+ ++*NS_STATIC_CAST(PRUint32*, arg);
+ const char *str;
+ atom->GetUTF8String(&str);
+ fputs(str, stdout);
+ fputs("\n", stdout);
+ }
+ return PL_DHASH_NEXT;
+}
+
+#endif
+
+static inline
+void PromoteToPermanent(AtomImpl* aAtom)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ {
+ nsrefcnt refcount = aAtom->GetRefCount();
+ do {
+ NS_LOG_RELEASE(aAtom, --refcount, "AtomImpl");
+ } while (refcount);
+ }
+#endif
+ aAtom = new (aAtom) PermanentAtomImpl();
+}
+
+void NS_PurgeAtomTable()
+{
+ if (gAtomTable.ops) {
+#ifdef DEBUG
+ if (PR_GetEnv("MOZ_DUMP_ATOM_LEAKS")) {
+ PRUint32 leaked = 0;
+ printf("*** %d atoms still exist (including permanent):\n",
+ gAtomTable.entryCount);
+ PL_DHashTableEnumerate(&gAtomTable, DumpAtomLeaks, &leaked);
+ printf("*** %u non-permanent atoms leaked\n", leaked);
+ }
+#endif
+ PL_DHashTableFinish(&gAtomTable);
+ gAtomTable.entryCount = 0;
+ gAtomTable.ops = nsnull;
+
+ if (gStaticAtomArena) {
+ PL_FinishArenaPool(gStaticAtomArena);
+ delete gStaticAtomArena;
+ gStaticAtomArena = nsnull;
+ }
+ }
+}
+
+AtomImpl::AtomImpl()
+{
+}
+
+AtomImpl::~AtomImpl()
+{
+ NS_PRECONDITION(gAtomTable.ops, "uninitialized atom hashtable");
+ // Permanent atoms are removed from the hashtable at shutdown, and we
+ // don't want to remove them twice. See comment above in
+ // |AtomTableClearEntry|.
+ if (!IsPermanent()) {
+ PL_DHashTableOperate(&gAtomTable, mString, PL_DHASH_REMOVE);
+ if (gAtomTable.entryCount == 0) {
+ PL_DHashTableFinish(&gAtomTable);
+ NS_ASSERTION(gAtomTable.entryCount == 0,
+ "PL_DHashTableFinish changed the entry count");
+ }
+ }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(AtomImpl, nsIAtom)
+
+NS_IMETHODIMP_(nsrefcnt) PermanentAtomImpl::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt) PermanentAtomImpl::Release()
+{
+ return 1;
+}
+
+/* virtual */ PRBool
+AtomImpl::IsPermanent()
+{
+ return PR_FALSE;
+}
+
+/* virtual */ PRBool
+PermanentAtomImpl::IsPermanent()
+{
+ return PR_TRUE;
+}
+
+void* AtomImpl::operator new ( size_t size, const nsACString& aString ) CPP_THROW_NEW
+{
+ /*
+ Note: since the |size| will initially also include the |PRUnichar| member
+ |mString|, our size calculation will give us one character too many.
+ We use that extra character for a zero-terminator.
+
+ Note: this construction is not guaranteed to be possible by the C++
+ compiler. A more reliable scheme is used by |nsShared[C]String|s, see
+ http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsSharedString.h#174
+ */
+ size += aString.Length() * sizeof(char);
+ AtomImpl* ii = NS_STATIC_CAST(AtomImpl*, ::operator new(size));
+
+ char* toBegin = &ii->mString[0];
+ nsACString::const_iterator fromBegin, fromEnd;
+ *copy_string(aString.BeginReading(fromBegin), aString.EndReading(fromEnd), toBegin) = '\0';
+ return ii;
+}
+
+void* PermanentAtomImpl::operator new ( size_t size, AtomImpl* aAtom ) CPP_THROW_NEW {
+ NS_ASSERTION(!aAtom->IsPermanent(),
+ "converting atom that's already permanent");
+
+ // Just let the constructor overwrite the vtable pointer.
+ return aAtom;
+}
+
+NS_IMETHODIMP
+AtomImpl::ToString(nsAString& aBuf)
+{
+ CopyUTF8toUTF16(nsDependentCString(mString), aBuf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::ToUTF8String(nsACString& aBuf)
+{
+ aBuf.Assign(mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::GetUTF8String(const char **aResult)
+{
+ NS_PRECONDITION(aResult, "null out param");
+ *aResult = mString;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::EqualsUTF8(const nsACString& aString, PRBool* aResult)
+{
+ *aResult = aString.Equals(mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::Equals(const nsAString& aString, PRBool* aResult)
+{
+ *aResult = NS_ConvertUTF16toUTF8(aString).Equals(mString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------
+
+// wrapper class for the nsStaticAtom struct
+
+NS_IMETHODIMP_(nsrefcnt)
+nsStaticAtomWrapper::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsStaticAtomWrapper::Release()
+{
+ return 1;
+}
+
+NS_IMPL_QUERY_INTERFACE1(nsStaticAtomWrapper, nsIAtom)
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::GetUTF8String(const char** aResult)
+{
+ *aResult = mStaticAtom->mString;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::ToString(nsAString& aBuf)
+{
+ // static should always be always ASCII, to allow tools like gperf
+ // to generate the tables, and to avoid unnecessary conversion
+ NS_ASSERTION(nsCRT::IsAscii(mStaticAtom->mString),
+ "Data loss - atom should be ASCII");
+ CopyASCIItoUCS2(nsDependentCString(mStaticAtom->mString), aBuf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::ToUTF8String(nsACString& aBuf)
+{
+ aBuf.Assign(mStaticAtom->mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::EqualsUTF8(const nsACString& aString, PRBool* aResult)
+{
+ *aResult = aString.Equals(mStaticAtom->mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::Equals(const nsAString& aString, PRBool* aResult)
+{
+ *aResult = NS_ConvertUCS2toUTF8(aString).Equals(mStaticAtom->mString);
+ return NS_OK;
+}
+//----------------------------------------------------------------------
+
+NS_COM nsIAtom* NS_NewAtom(const char* isolatin1)
+{
+ return NS_NewAtom(nsDependentCString(isolatin1));
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom(const char* isolatin1)
+{
+ return NS_NewPermanentAtom(NS_ConvertASCIItoUCS2(isolatin1));
+}
+
+static nsStaticAtomWrapper*
+WrapStaticAtom(const nsStaticAtom* aAtom)
+{
+ if (!gStaticAtomArena) {
+ gStaticAtomArena = new PLArenaPool;
+ if (!gStaticAtomArena)
+ return nsnull;
+
+ PL_INIT_ARENA_POOL(gStaticAtomArena, "nsStaticAtomArena", 4096);
+ }
+
+ void* mem;
+ PL_ARENA_ALLOCATE(mem, gStaticAtomArena, sizeof(nsStaticAtom));
+
+ nsStaticAtomWrapper* wrapper =
+ new (mem) nsStaticAtomWrapper(aAtom);
+
+ return wrapper;
+}
+
+static AtomTableEntry* GetAtomHashEntry(const char* aString)
+{
+ if (!gAtomTable.ops &&
+ !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0,
+ sizeof(AtomTableEntry), 2048)) {
+ gAtomTable.ops = nsnull;
+ return nsnull;
+ }
+ return NS_STATIC_CAST(AtomTableEntry*,
+ PL_DHashTableOperate(&gAtomTable,
+ aString,
+ PL_DHASH_ADD));
+}
+
+NS_COM nsresult
+NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
+{
+ // this does two things:
+ // 1) wraps each static atom in a wrapper, if necessary
+ // 2) initializes the address pointed to by each mAtom slot
+
+ for (PRUint32 i=0; i<aAtomCount; i++) {
+ NS_ASSERTION(nsCRT::IsAscii(aAtoms[i].mString),
+ "Static atoms must be ASCII!");
+ AtomTableEntry *he =
+ GetAtomHashEntry(aAtoms[i].mString);
+
+ if (he->HasValue() && aAtoms[i].mAtom) {
+ // there already is an atom with this name in the table.. but we
+ // still have to update mAtom
+ if (!he->IsStaticAtom() && !he->GetAtomImpl()->IsPermanent()) {
+ // since we wanted to create a static atom but there is
+ // already one there, we convert it to a non-refcounting
+ // permanent atom
+ PromoteToPermanent(he->GetAtomImpl());
+ }
+
+ // and now, if the consumer wants to remember this value in a
+ // slot, we do so
+ if (aAtoms[i].mAtom)
+ *aAtoms[i].mAtom = he->GetAtom();
+ }
+
+ else {
+ nsStaticAtomWrapper* atom = WrapStaticAtom(&aAtoms[i]);
+ NS_ASSERTION(atom, "Failed to wrap static atom");
+
+ // but even if atom is null, no real difference in code..
+ he->SetStaticAtomWrapper(atom);
+ if (aAtoms[i].mAtom)
+ *aAtoms[i].mAtom = atom;
+ }
+ }
+ return NS_OK;
+}
+
+NS_COM nsIAtom* NS_NewAtom( const nsAString& aString )
+{
+ NS_ConvertUCS2toUTF8 utf8String(aString);
+
+ return NS_NewAtom(utf8String);
+}
+
+NS_COM
+nsIAtom*
+NS_NewAtom( const nsACString& aString )
+{
+ AtomTableEntry *he = GetAtomHashEntry(PromiseFlatCString(aString).get());
+
+ if (he->HasValue())
+ return he->GetAtom();
+
+ AtomImpl* atom = new (aString) AtomImpl();
+ he->SetAtomImpl(atom);
+ if (!atom) {
+ PL_DHashTableRawRemove(&gAtomTable, he);
+ return nsnull;
+ }
+
+ NS_ADDREF(atom);
+ return atom;
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom( const nsAString& aString )
+{
+ return NS_NewPermanentAtom(NS_ConvertUCS2toUTF8(aString));
+}
+
+NS_COM
+nsIAtom* NS_NewPermanentAtom( const nsACString& aString )
+{
+ AtomTableEntry *he = GetAtomHashEntry(PromiseFlatCString(aString).get());
+
+ if (he->HasValue() && he->IsStaticAtom())
+ return he->GetStaticAtomWrapper();
+
+ // either there is no atom and we'll create an AtomImpl,
+ // or there is an existing AtomImpl
+ AtomImpl* atom = he->GetAtomImpl();
+
+ if (atom) {
+ // ensure that it's permanent
+ if (!atom->IsPermanent()) {
+ PromoteToPermanent(atom);
+ }
+ } else {
+ // otherwise, make a new atom
+ atom = new (aString) PermanentAtomImpl();
+ he->SetAtomImpl(atom);
+ if ( !atom ) {
+ PL_DHashTableRawRemove(&gAtomTable, he);
+ return nsnull;
+ }
+ }
+
+ NS_ADDREF(atom);
+ return atom;
+}
+
+NS_COM nsIAtom* NS_NewAtom( const PRUnichar* str )
+{
+ return NS_NewAtom(NS_ConvertUCS2toUTF8(str));
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom( const PRUnichar* str )
+{
+ return NS_NewPermanentAtom(nsDependentString(str));
+}
+
+NS_COM nsrefcnt NS_GetNumberOfAtoms(void)
+{
+ return gAtomTable.entryCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h
new file mode 100644
index 00000000..d8971cf7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAtomTable_h__
+#define nsAtomTable_h__
+
+#include "nsIAtom.h"
+
+/**
+ * A threadsafely-refcounted implementation of nsIAtom. Note that
+ * AtomImpl objects are sometimes converted into PermanentAtomImpl
+ * objects using placement new and just overwriting the vtable pointer.
+ */
+
+class AtomImpl : public nsIAtom {
+public:
+ AtomImpl();
+
+protected:
+ // We don't need a virtual destructor here because PermanentAtomImpl
+ // deletions aren't handled through Release().
+ ~AtomImpl();
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIATOM
+
+ virtual PRBool IsPermanent();
+
+ void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW;
+
+ void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+
+ // for |#ifdef NS_BUILD_REFCNT_LOGGING| access to reference count
+ nsrefcnt GetRefCount() { return mRefCnt; }
+
+ // Actually more; 0 terminated. This slot is reserved for the
+ // terminating zero.
+ char mString[1];
+};
+
+/**
+ * A non-refcounted implementation of nsIAtom.
+ */
+
+class PermanentAtomImpl : public AtomImpl {
+public:
+#ifdef AIX
+ PermanentAtomImpl() : AtomImpl() {}
+#endif
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+
+ virtual PRBool IsPermanent();
+
+ void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW {
+ return AtomImpl::operator new(size, aString);
+ }
+ void* operator new(size_t size, AtomImpl* aAtom) CPP_THROW_NEW;
+
+};
+
+void NS_PurgeAtomTable();
+
+#endif // nsAtomTable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h
new file mode 100644
index 00000000..84011369
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is auto buffer template.
+ *
+ * The Initial Developer of the Original Code is
+ * Conrad Carlen <ccarlen@mac.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jungshik Shin <jshin@mailaps.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAutoBuffer_h__
+#define nsAutoBuffer_h__
+
+#ifndef nsMemory_h__
+#include "nsMemory.h"
+#endif
+
+/**
+ * A buffer which will use stack space if the requested size will
+ * fit in the stack buffer and allocate from the heap if not.
+ *
+ * Below is a usage example :
+ *
+ * typedef nsAutoBuffer<PRUnichar, 256> nsAutoUnicharBuffer;
+ *
+ * nsAutoUnicharBuffer buffer;
+ *
+ * if (!buffer.EnsureElemCapacity(initialLength))
+ * return NS_ERROR_OUT_OF_MEMORY;
+ *
+ * PRUnichar *unicharPtr = buffer.get();
+ *
+ * // add PRUnichar's to the buffer pointed to by |unicharPtr| as long as
+ * // the number of PRUnichar's is less than |intialLength|
+ *
+ * // increase the capacity
+ * if (!buffer.AddElemCapacity(extraLength))
+ * return NS_ERROR_OUT_OF_MEMORY
+ *
+ * unicharPtr = buffer.get() + initialLength;
+ *
+ * //continue to add PRUnichar's....
+ */
+
+template <class T, PRInt32 sz>
+class nsAutoBuffer
+{
+public:
+ nsAutoBuffer() :
+ mBufferPtr(mStackBuffer),
+ mCurElemCapacity(sz)
+ {
+ }
+
+ ~nsAutoBuffer()
+ {
+ if (mBufferPtr != mStackBuffer)
+ nsMemory::Free(mBufferPtr);
+ }
+
+ PRBool EnsureElemCapacity(PRInt32 inElemCapacity)
+ {
+ if (inElemCapacity <= mCurElemCapacity)
+ return PR_TRUE;
+
+ T* newBuffer;
+
+ if (mBufferPtr != mStackBuffer)
+ newBuffer = (T*)nsMemory::Realloc((void *)mBufferPtr, inElemCapacity * sizeof(T));
+ else
+ newBuffer = (T*)nsMemory::Alloc(inElemCapacity * sizeof(T));
+
+ if (!newBuffer)
+ return PR_FALSE;
+
+ if (mBufferPtr != mStackBuffer)
+ nsMemory::Free(mBufferPtr);
+
+ mBufferPtr = newBuffer;
+ mCurElemCapacity = inElemCapacity;
+ return PR_TRUE;
+ }
+
+ PRBool AddElemCapacity(PRInt32 inElemCapacity)
+ {
+ return EnsureElemCapacity(mCurElemCapacity + inElemCapacity);
+ }
+
+ T* get() const { return mBufferPtr; }
+ PRInt32 GetElemCapacity() const { return mCurElemCapacity; }
+
+protected:
+
+ T *mBufferPtr;
+ T mStackBuffer[sz];
+ PRInt32 mCurElemCapacity;
+};
+
+#endif // nsAutoBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h
new file mode 100644
index 00000000..92300c2f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsBaseHashtable_h__
+#define nsBaseHashtable_h__
+
+#include "nsTHashtable.h"
+#include "prlock.h"
+#include "nsDebug.h"
+
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtable; // forward declaration
+
+/**
+ * the private nsTHashtable::EntryType class used by nsBaseHashtable
+ * @see nsTHashtable for the specification of this class
+ * @see nsBaseHashtable for template parameters
+ */
+template<class KeyClass,class DataType>
+class nsBaseHashtableET : public KeyClass
+{
+public:
+ DataType mData;
+ friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
+
+private:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef typename KeyClass::KeyTypePointer KeyTypePointer;
+
+ nsBaseHashtableET(KeyTypePointer aKey);
+ nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>& toCopy);
+ ~nsBaseHashtableET();
+};
+
+/**
+ * templated hashtable for simple data types
+ * This class manages simple data types that do not need construction or
+ * destruction. Thread-safety is optional, via a flag in Init()
+ *
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param DataType the datatype stored in the hashtable,
+ * for example, PRUint32 or nsCOMPtr. If UserDataType is not the same,
+ * DataType must implicitly cast to UserDataType
+ * @param UserDataType the user sees, for example PRUint32 or nsISupports*
+ */
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtable :
+ protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
+
+ // default constructor+destructor are fine
+
+ /**
+ * Initialize the object.
+ * @param initSize the initial number of buckets in the hashtable,
+ * default 16
+ * @param threadSafe whether to provide read/write
+ * locking on all class methods
+ * @return PR_TRUE if the object was initialized properly.
+ */
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
+ { return nsTHashtable<EntryType>::Init(initSize); }
+
+ /**
+ * Check whether the table has been initialized.
+ * This function is especially useful for static hashtables.
+ * @return PR_TRUE if the table has been initialized.
+ */
+ PRBool IsInitialized() const { return this->mTable.entrySize; }
+
+ /**
+ * Return the number of entries in the table.
+ * @return number of entries
+ */
+ PRUint32 Count() const
+ { return nsTHashtable<EntryType>::Count(); }
+
+ /**
+ * retrieve the value for a key.
+ * @param aKey the key to retreive
+ * @param pData data associated with this key will be placed at this
+ * pointer. If you only need to check if the key exists, pData
+ * may be null.
+ * @return PR_TRUE if the key exists. If key does not exist, pData is not
+ * modified.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const
+ {
+ EntryType* ent = this->GetEntry(aKey);
+
+ if (!ent)
+ return PR_FALSE;
+
+ if (pData)
+ *pData = ent->mData;
+
+ return PR_TRUE;
+ }
+
+ /**
+ * put a new value for the associated key
+ * @param aKey the key to put
+ * @param aData the new data
+ * @return always PR_TRUE, unless memory allocation failed
+ */
+ PRBool Put(KeyType aKey, UserDataType aData)
+ {
+ EntryType* ent = this->PutEntry(aKey);
+
+ if (!ent)
+ return PR_FALSE;
+
+ ent->mData = aData;
+
+ return PR_TRUE;
+ }
+
+ /**
+ * remove the data for the associated key
+ * @param aKey the key to remove from the hashtable
+ */
+ void Remove(KeyType aKey) { this->RemoveEntry(aKey); }
+
+ /**
+ * function type provided by the application for enumeration.
+ * @param aKey the key being enumerated
+ * @param aData data being enumerated
+ * @parm userArg passed unchanged from Enumerate
+ * @return either
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
+ */
+ typedef PLDHashOperator
+ (*PR_CALLBACK EnumReadFunction)(KeyType aKey,
+ UserDataType aData,
+ void* userArg);
+
+ /**
+ * enumerate entries in the hashtable, without allowing changes
+ * this function read-locks the hashtable, so other threads may read keys
+ * at the same time in multi-thread environments.
+ * @param enumFunc enumeration callback
+ * @param userArg passed unchanged to the EnumReadFunction
+ */
+ PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
+ {
+ NS_ASSERTION(this->mTable.entrySize,
+ "nsBaseHashtable was not initialized properly.");
+
+ s_EnumReadArgs enumData = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*, &this->mTable),
+ s_EnumReadStub,
+ &enumData);
+ }
+
+ /**
+ * function type provided by the application for enumeration.
+ * @param aKey the key being enumerated
+ * @param aData Reference to data being enumerated, may be altered. e.g. for
+ * nsInterfaceHashtable this is an nsCOMPtr reference...
+ * @parm userArg passed unchanged from Enumerate
+ * @return bitflag combination of
+ * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
+ */
+ typedef PLDHashOperator
+ (*PR_CALLBACK EnumFunction)(KeyType aKey,
+ DataType& aData,
+ void* userArg);
+
+ /**
+ * enumerate entries in the hashtable, allowing changes. This
+ * functions write-locks the hashtable.
+ * @param enumFunc enumeration callback
+ * @param userArg passed unchanged to the EnumFunction
+ */
+ PRUint32 Enumerate(EnumFunction enumFunc, void* userArg)
+ {
+ NS_ASSERTION(this->mTable.entrySize,
+ "nsBaseHashtable was not initialized properly.");
+
+ s_EnumArgs enumData = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(&this->mTable,
+ s_EnumStub,
+ &enumData);
+ }
+
+ /**
+ * reset the hashtable, removing all entries
+ */
+ void Clear() { nsTHashtable<EntryType>::Clear(); }
+
+protected:
+ /**
+ * used internally during EnumerateRead. Allocated on the stack.
+ * @param func the enumerator passed to EnumerateRead
+ * @param userArg the userArg passed to EnumerateRead
+ */
+ struct s_EnumReadArgs
+ {
+ EnumReadFunction func;
+ void* userArg;
+ };
+
+ static PLDHashOperator s_EnumReadStub(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg);
+
+ struct s_EnumArgs
+ {
+ EnumFunction func;
+ void* userArg;
+ };
+
+ static PLDHashOperator s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg);
+};
+
+/**
+ * This class is a thread-safe version of nsBaseHashtable.
+ */
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtableMT :
+ protected nsBaseHashtable<KeyClass,DataType,UserDataType>
+{
+public:
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
+
+ nsBaseHashtableMT() : mLock(nsnull) { }
+ ~nsBaseHashtableMT();
+
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
+ PRBool IsInitialized() const { return (PRBool) mLock; }
+ PRUint32 Count() const;
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+ PRBool Put(KeyType aKey, UserDataType aData);
+ void Remove(KeyType aKey);
+
+ PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
+ PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
+ void Clear();
+
+protected:
+ PRLock* mLock;
+};
+
+
+//
+// nsBaseHashtableET definitions
+//
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
+ KeyClass(aKey)
+{ }
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
+ (nsBaseHashtableET<KeyClass,DataType>& toCopy) :
+ KeyClass(toCopy),
+ mData(toCopy.mData)
+{ }
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
+{ }
+
+
+//
+// nsBaseHashtable definitions
+//
+
+template<class KeyClass,class DataType,class UserDataType>
+PLDHashOperator
+nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
+ (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
+{
+ EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
+ s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
+
+ PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
+
+ NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
+ "PL_DHASH_REMOVE return during const enumeration; ignoring.");
+
+ if (res & PL_DHASH_STOP)
+ return PL_DHASH_STOP;
+
+ return PL_DHASH_NEXT;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PLDHashOperator
+nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
+ (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
+{
+ EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
+ s_EnumArgs* eargs = (s_EnumArgs*) arg;
+
+ return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
+}
+
+
+//
+// nsBaseHashtableMT definitions
+//
+
+template<class KeyClass,class DataType,class UserDataType>
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
+{
+ if (this->mLock)
+ PR_DestroyLock(this->mLock);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
+{
+ if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
+ return PR_FALSE;
+
+ this->mLock = PR_NewLock();
+ NS_WARN_IF_FALSE(this->mLock, "Error creating lock during nsBaseHashtableL::Init()");
+
+ return (this->mLock != nsnull);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
+{
+ PR_Lock(this->mLock);
+ PRUint32 count = nsTHashtable<EntryType>::Count();
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType aKey,
+ UserDataType* pData) const
+{
+ PR_Lock(this->mLock);
+ PRBool res =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
+ PR_Unlock(this->mLock);
+
+ return res;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType aKey,
+ UserDataType aData)
+{
+ PR_Lock(this->mLock);
+ PRBool res =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
+ PR_Unlock(this->mLock);
+
+ return res;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+void
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
+{
+ PR_Lock(this->mLock);
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
+ PR_Unlock(this->mLock);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
+ (EnumReadFunction fEnumCall, void* userArg) const
+{
+ PR_Lock(this->mLock);
+ PRUint32 count =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
+ (EnumFunction fEnumCall, void* userArg)
+{
+ PR_Lock(this->mLock);
+ PRUint32 count =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+void
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
+{
+ PR_Lock(this->mLock);
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
+ PR_Unlock(this->mLock);
+}
+
+#endif // nsBaseHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp
new file mode 100644
index 00000000..a51ff9d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsByteBuffer.h"
+#include "nsIInputStream.h"
+#include "nsCRT.h"
+
+#define MIN_BUFFER_SIZE 32
+
+ByteBufferImpl::ByteBufferImpl(void)
+ : mBuffer(NULL), mSpace(0), mLength(0)
+{
+}
+
+NS_IMETHODIMP
+ByteBufferImpl::Init(PRUint32 aBufferSize)
+{
+ if (aBufferSize < MIN_BUFFER_SIZE) {
+ aBufferSize = MIN_BUFFER_SIZE;
+ }
+ mSpace = aBufferSize;
+ mLength = 0;
+ mBuffer = new char[aBufferSize];
+ return mBuffer ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_ISUPPORTS1(ByteBufferImpl,nsIByteBuffer)
+
+ByteBufferImpl::~ByteBufferImpl()
+{
+ if (nsnull != mBuffer) {
+ delete[] mBuffer;
+ mBuffer = nsnull;
+ }
+ mLength = 0;
+}
+
+NS_METHOD
+ByteBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ ByteBufferImpl* it = new ByteBufferImpl();
+ if (nsnull == it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(it);
+ nsresult rv = it->QueryInterface(aIID, (void**)aResult);
+ NS_RELEASE(it);
+ return rv;
+}
+
+NS_IMETHODIMP_(PRUint32)
+ByteBufferImpl::GetLength(void) const
+{
+ return mLength;
+}
+
+NS_IMETHODIMP_(PRUint32)
+ByteBufferImpl::GetBufferSize(void) const
+{
+ return mSpace;
+}
+
+NS_IMETHODIMP_(char*)
+ByteBufferImpl::GetBuffer(void) const
+{
+ return mBuffer;
+}
+
+NS_IMETHODIMP_(PRBool)
+ByteBufferImpl::Grow(PRUint32 aNewSize)
+{
+ if (aNewSize < MIN_BUFFER_SIZE) {
+ aNewSize = MIN_BUFFER_SIZE;
+ }
+ char* newbuf = new char[aNewSize];
+ if (nsnull != newbuf) {
+ if (0 != mLength) {
+ memcpy(newbuf, mBuffer, mLength);
+ }
+ delete[] mBuffer;
+ mBuffer = newbuf;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRInt32)
+ByteBufferImpl::Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep)
+{
+ NS_PRECONDITION(nsnull != aStream, "null stream");
+ NS_PRECONDITION(aKeep <= mLength, "illegal keep count");
+ if ((nsnull == aStream) || (PRUint32(aKeep) > PRUint32(mLength))) {
+ // whoops
+ *aErrorCode = NS_BASE_STREAM_ILLEGAL_ARGS;
+ return -1;
+ }
+
+ if (0 != aKeep) {
+ // Slide over kept data
+ memmove(mBuffer, mBuffer + (mLength - aKeep), aKeep);
+ }
+
+ // Read in some new data
+ mLength = aKeep;
+ PRUint32 nb;
+ *aErrorCode = aStream->Read(mBuffer + aKeep, mSpace - aKeep, &nb);
+ if (NS_SUCCEEDED(*aErrorCode)) {
+ mLength += nb;
+ }
+ else
+ nb = 0;
+ return nb;
+}
+
+NS_COM nsresult NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize)
+{
+ nsresult rv;
+ nsIByteBuffer* buf;
+ rv = ByteBufferImpl::Create(aOuter, NS_GET_IID(nsIByteBuffer), (void**)&buf);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = buf->Init(aBufferSize);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(buf);
+ return rv;
+ }
+ *aInstancePtrResult = buf;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h
new file mode 100644
index 00000000..0a474570
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsByteBuffer_h__
+#define nsByteBuffer_h__
+
+#include "nsIByteBuffer.h"
+
+class ByteBufferImpl : public nsIByteBuffer {
+public:
+ ByteBufferImpl(void);
+
+ NS_DECL_ISUPPORTS
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_IMETHOD Init(PRUint32 aBufferSize);
+ NS_IMETHOD_(PRUint32) GetLength(void) const;
+ NS_IMETHOD_(PRUint32) GetBufferSize(void) const;
+ NS_IMETHOD_(char*) GetBuffer() const;
+ NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize);
+ NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep);
+
+ char* mBuffer;
+ PRUint32 mSpace;
+ PRUint32 mLength;
+private:
+ ~ByteBufferImpl();
+};
+
+#endif // nsByteBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp
new file mode 100644
index 00000000..9a270223
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a COM aware array class.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+
+PR_STATIC_CALLBACK(PRBool) ReleaseObjects(void* aElement, void*);
+
+// implementations of non-trivial methods in nsCOMArray_base
+
+// copy constructor - we can't just memcpy here, because
+// we have to make sure we own our own array buffer, and that each
+// object gets another AddRef()
+nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
+{
+ // make sure we do only one allocation
+ mArray.SizeTo(aOther.Count());
+ AppendObjects(aOther);
+}
+
+nsCOMArray_base::~nsCOMArray_base()
+{
+ PRInt32 count = Count(), i;
+ for (i = 0; i < count; ++i) {
+ nsISupports* obj = ObjectAt(i);
+ NS_IF_RELEASE(obj);
+ }
+}
+
+PRInt32
+nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
+ NS_ENSURE_TRUE(aObject, -1);
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
+ NS_ENSURE_TRUE(supports, -1);
+
+ PRInt32 i, count;
+ PRInt32 retval = -1;
+ count = mArray.Count();
+ for (i = 0; i < count; ++i) {
+ nsCOMPtr<nsISupports> arrayItem =
+ do_QueryInterface(NS_REINTERPRET_CAST(nsISupports*,mArray.ElementAt(i)));
+ if (arrayItem == supports) {
+ retval = i;
+ break;
+ }
+ }
+ return retval;
+}
+
+PRBool
+nsCOMArray_base::InsertObjectAt(nsISupports* aObject, PRInt32 aIndex) {
+ PRBool result = mArray.InsertElementAt(aObject, aIndex);
+ if (result)
+ NS_IF_ADDREF(aObject);
+ return result;
+}
+
+PRBool
+nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, PRInt32 aIndex) {
+ PRBool result = mArray.InsertElementsAt(aObjects.mArray, aIndex);
+ if (result) {
+ // need to addref all these
+ PRInt32 count = aObjects.Count();
+ for (PRInt32 i = 0; i < count; ++i) {
+ NS_IF_ADDREF(aObjects.ObjectAt(i));
+ }
+ }
+ return result;
+}
+
+PRBool
+nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, PRInt32 aIndex)
+{
+ // its ok if oldObject is null here
+ nsISupports *oldObject =
+ NS_REINTERPRET_CAST(nsISupports*, mArray.SafeElementAt(aIndex));
+
+ PRBool result = mArray.ReplaceElementAt(aObject, aIndex);
+
+ // ReplaceElementAt could fail, such as if the array grows
+ // so only release the existing object if the replacement succeeded
+ if (result) {
+ // Make sure to addref first, in case aObject == oldObject
+ NS_IF_ADDREF(aObject);
+ NS_IF_RELEASE(oldObject);
+ }
+ return result;
+}
+
+PRBool
+nsCOMArray_base::RemoveObject(nsISupports *aObject)
+{
+ PRBool result = mArray.RemoveElement(aObject);
+ if (result)
+ NS_IF_RELEASE(aObject);
+ return result;
+}
+
+PRBool
+nsCOMArray_base::RemoveObjectAt(PRInt32 aIndex)
+{
+ nsISupports* element = ObjectAt(aIndex);
+ if (element) {
+ PRBool result = mArray.RemoveElementAt(aIndex);
+ if (result)
+ NS_IF_RELEASE(element);
+ return result;
+ }
+ return PR_FALSE;
+}
+
+// useful for destructors
+PRBool
+ReleaseObjects(void* aElement, void*)
+{
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, aElement);
+ NS_IF_RELEASE(element);
+ return PR_TRUE;
+}
+
+void
+nsCOMArray_base::Clear()
+{
+ mArray.EnumerateForwards(ReleaseObjects, nsnull);
+ mArray.Clear();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h
new file mode 100644
index 00000000..cbb728c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a COM aware array class.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCOMArray_h__
+#define nsCOMArray_h__
+
+#include "nsVoidArray.h"
+#include "nsISupports.h"
+
+// See below for the definition of nsCOMArray<T>
+
+// a class that's nsISupports-specific, so that we can contain the
+// work of this class in the XPCOM dll
+class NS_COM nsCOMArray_base
+{
+ friend class nsArray;
+protected:
+ nsCOMArray_base() {}
+ nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {}
+ nsCOMArray_base(const nsCOMArray_base& other);
+ ~nsCOMArray_base();
+
+ PRInt32 IndexOf(nsISupports* aObject) const {
+ return mArray.IndexOf(aObject);
+ }
+
+ PRInt32 IndexOfObject(nsISupports* aObject) const;
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) {
+ return mArray.EnumerateForwards(aFunc, aData);
+ }
+
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData) {
+ return mArray.EnumerateBackwards(aFunc, aData);
+ }
+
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData) {
+ mArray.Sort(aFunc, aData);
+ }
+
+ // any method which is not a direct forward to mArray should
+ // avoid inline bodies, so that the compiler doesn't inline them
+ // all over the place
+ void Clear();
+ PRBool InsertObjectAt(nsISupports* aObject, PRInt32 aIndex);
+ PRBool InsertObjectsAt(const nsCOMArray_base& aObjects, PRInt32 aIndex);
+ PRBool ReplaceObjectAt(nsISupports* aObject, PRInt32 aIndex);
+ PRBool AppendObject(nsISupports *aObject) {
+ return InsertObjectAt(aObject, Count());
+ }
+ PRBool AppendObjects(const nsCOMArray_base& aObjects) {
+ return InsertObjectsAt(aObjects, Count());
+ }
+ PRBool RemoveObject(nsISupports *aObject);
+ PRBool RemoveObjectAt(PRInt32 aIndex);
+
+public:
+ // override nsVoidArray stuff so that they can be accessed by
+ // consumers of nsCOMArray
+ PRInt32 Count() const {
+ return mArray.Count();
+ }
+
+ nsISupports* ObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(nsISupports*, mArray.FastElementAt(aIndex));
+ }
+
+ nsISupports* SafeObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(nsISupports*, mArray.SafeElementAt(aIndex));
+ }
+
+ nsISupports* operator[](PRInt32 aIndex) const {
+ return ObjectAt(aIndex);
+ }
+
+private:
+
+ // the actual storage
+ nsVoidArray mArray;
+
+ // don't implement these, defaults will muck with refcounts!
+ nsCOMArray_base& operator=(const nsCOMArray_base& other);
+};
+
+// a non-XPCOM, refcounting array of XPCOM objects
+// used as a member variable or stack variable - this object is NOT
+// refcounted, but the objects that it holds are
+//
+// most of the read-only accessors like ObjectAt()/etc do NOT refcount
+// on the way out. This means that you can do one of two things:
+//
+// * does an addref, but holds onto a reference
+// nsCOMPtr<T> foo = array[i];
+//
+// * avoids the refcount, but foo might go stale if array[i] is ever
+// * modified/removed. Be careful not to NS_RELEASE(foo)!
+// T* foo = array[i];
+//
+// This array will accept null as an argument for any object, and will
+// store null in the array, just like nsVoidArray. But that also means
+// that methods like ObjectAt() may return null when referring to an
+// existing, but null entry in the array.
+template <class T>
+class nsCOMArray : public nsCOMArray_base
+{
+ public:
+ nsCOMArray() {}
+ nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {}
+
+ // only to be used by trusted classes who are going to pass us the
+ // right type!
+ nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) { }
+
+ ~nsCOMArray() {}
+
+ // these do NOT refcount on the way out, for speed
+ T* ObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(T*,nsCOMArray_base::ObjectAt(aIndex));
+ }
+
+ // these do NOT refcount on the way out, for speed
+ T* SafeObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(T*,nsCOMArray_base::SafeObjectAt(aIndex));
+ }
+
+ // indexing operator for syntactic sugar
+ T* operator[](PRInt32 aIndex) const {
+ return ObjectAt(aIndex);
+ }
+
+ // index of the element in question.. does NOT refcount
+ // note: this does not check COM object identity. Use
+ // IndexOfObject() for that purpose
+ PRInt32 IndexOf(T* aObject) const {
+ return nsCOMArray_base::IndexOf(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // index of the element in question.. be careful!
+ // this is much slower than IndexOf() because it uses
+ // QueryInterface to determine actual COM identity of the object
+ // if you need to do this frequently then consider enforcing
+ // COM object identity before adding/comparing elements
+ PRInt32 IndexOfObject(T* aObject) const {
+ return nsCOMArray_base::IndexOfObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // inserts aObject at aIndex, shifting the objects at aIndex and
+ // later to make space
+ PRBool InsertObjectAt(T* aObject, PRInt32 aIndex) {
+ return nsCOMArray_base::InsertObjectAt(NS_STATIC_CAST(nsISupports*, aObject), aIndex);
+ }
+
+ // inserts the objects from aObject at aIndex, shifting the
+ // objects at aIndex and later to make space
+ PRBool InsertObjectsAt(const nsCOMArray<T>& aObjects, PRInt32 aIndex) {
+ return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex);
+ }
+
+ // replaces an existing element. Warning: if the array grows,
+ // the newly created entries will all be null
+ PRBool ReplaceObjectAt(T* aObject, PRInt32 aIndex) {
+ return nsCOMArray_base::ReplaceObjectAt(NS_STATIC_CAST(nsISupports*, aObject), aIndex);
+ }
+
+ // override nsVoidArray stuff so that they can be accessed by
+ // other methods
+
+ // elements in the array (including null elements!)
+ PRInt32 Count() const {
+ return nsCOMArray_base::Count();
+ }
+
+ // remove all elements in the array, and call NS_RELEASE on each one
+ void Clear() {
+ nsCOMArray_base::Clear();
+ }
+
+ // Enumerator callback function. Return PR_FALSE to stop
+ // Here's a more readable form:
+ // PRBool PR_CALLBACK enumerate(T* aElement, void* aData)
+ typedef PRBool (* PR_CALLBACK nsCOMArrayEnumFunc)
+ (T* aElement, void *aData);
+
+ // enumerate through the array with a callback.
+ PRBool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) {
+ return nsCOMArray_base::EnumerateForwards(nsVoidArrayEnumFunc(aFunc),
+ aData);
+ }
+
+ PRBool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData) {
+ return nsCOMArray_base::EnumerateBackwards(nsVoidArrayEnumFunc(aFunc),
+ aData);
+ }
+
+ typedef int (* PR_CALLBACK nsCOMArrayComparatorFunc)
+ (T* aElement1, T* aElement2, void* aData);
+
+ void Sort(nsCOMArrayComparatorFunc aFunc, void* aData) {
+ nsCOMArray_base::Sort(nsVoidArrayComparatorFunc(aFunc), aData);
+ }
+
+ // append an object, growing the array as necessary
+ PRBool AppendObject(T *aObject) {
+ return nsCOMArray_base::AppendObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // append objects, growing the array as necessary
+ PRBool AppendObjects(const nsCOMArray<T>& aObjects) {
+ return nsCOMArray_base::AppendObjects(aObjects);
+ }
+
+ // remove the first instance of the given object and shrink the
+ // array as necessary
+ // Warning: if you pass null here, it will remove the first null element
+ PRBool RemoveObject(T *aObject) {
+ return nsCOMArray_base::RemoveObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // remove an element at a specific position, shrinking the array
+ // as necessary
+ PRBool RemoveObjectAt(PRInt32 aIndex) {
+ return nsCOMArray_base::RemoveObjectAt(aIndex);
+ }
+
+private:
+
+ // don't implement these!
+ nsCOMArray<T>& operator=(const nsCOMArray<T>& other);
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp
new file mode 100644
index 00000000..23392f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp
@@ -0,0 +1,534 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/**
+ * MODULE NOTES:
+ * @update gess7/30/98
+ *
+ * Much as I hate to do it, we were using string compares wrong.
+ * Often, programmers call functions like strcmp(s1,s2), and pass
+ * one or more null strings. Rather than blow up on these, I've
+ * added quick checks to ensure that cases like this don't cause
+ * us to fail.
+ *
+ * In general, if you pass a null into any of these string compare
+ * routines, we simply return 0.
+ */
+
+
+#include "nsCRT.h"
+#include "nsIServiceManager.h"
+
+// XXX Bug: These tables don't lowercase the upper 128 characters properly
+
+// This table maps uppercase characters to lower case characters;
+// characters that are neither upper nor lower case are unaffected.
+static const unsigned char kUpper2Lower[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64,
+
+ // upper band mapped to lower [A-Z] => [a-z]
+ 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,
+
+ 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static const unsigned char kLower2Upper[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96,
+
+ // lower band mapped to upper [a-z] => [A-Z]
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+
+ 123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+//----------------------------------------------------------------------
+
+char nsCRT::ToUpper(char aChar)
+{
+ return (char)kLower2Upper[(unsigned char)aChar];
+}
+
+char nsCRT::ToLower(char aChar)
+{
+ return (char)kUpper2Lower[(unsigned char)aChar];
+}
+
+PRBool nsCRT::IsUpper(char aChar)
+{
+ return aChar != nsCRT::ToLower(aChar);
+}
+
+PRBool nsCRT::IsLower(char aChar)
+{
+ return aChar != nsCRT::ToUpper(aChar);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// My lovely strtok routine
+
+#define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7)))
+#define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7)))
+#define DELIM_TABLE_SIZE 32
+
+char* nsCRT::strtok(char* string, const char* delims, char* *newStr)
+{
+ NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null.");
+
+ char delimTable[DELIM_TABLE_SIZE];
+ PRUint32 i;
+ char* result;
+ char* str = string;
+
+ for (i = 0; i < DELIM_TABLE_SIZE; i++)
+ delimTable[i] = '\0';
+
+ for (i = 0; delims[i]; i++) {
+ SET_DELIM(delimTable, NS_STATIC_CAST(PRUint8, delims[i]));
+ }
+ NS_ASSERTION(delims[i] == '\0', "too many delimiters");
+
+ // skip to beginning
+ while (*str && IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
+ str++;
+ }
+ result = str;
+
+ // fix up the end of the token
+ while (*str) {
+ if (IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
+ *str++ = '\0';
+ break;
+ }
+ str++;
+ }
+ *newStr = str;
+
+ return str == result ? NULL : result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+PRUint32 nsCRT::strlen(const PRUnichar* s)
+{
+ PRUint32 len = 0;
+ if(s) {
+ while (*s++ != 0) {
+ len++;
+ }
+ }
+ return len;
+}
+
+
+/**
+ * Compare unichar string ptrs, stopping at the 1st null
+ * NOTE: If both are null, we return 0.
+ * NOTE: We terminate the search upon encountering a NULL
+ *
+ * @update gess 11/10/99
+ * @param s1 and s2 both point to unichar strings
+ * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
+ */
+PRInt32 nsCRT::strcmp(const PRUnichar* s1, const PRUnichar* s2) {
+ if(s1 && s2) {
+ for (;;) {
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = *s2++;
+ if (c1 != c2) {
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ if ((0==c1) || (0==c2)) break;
+ }
+ }
+ else {
+ if (s1) // s2 must have been null
+ return -1;
+ if (s2) // s1 must have been null
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Compare unichar string ptrs, stopping at the 1st null or nth char.
+ * NOTE: If either is null, we return 0.
+ * NOTE: We DO NOT terminate the search upon encountering NULL's before N
+ *
+ * @update gess 11/10/99
+ * @param s1 and s2 both point to unichar strings
+ * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
+ */
+PRInt32 nsCRT::strncmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n) {
+ if(s1 && s2) {
+ if(n != 0) {
+ do {
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = *s2++;
+ if (c1 != c2) {
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ } while (--n != 0);
+ }
+ }
+ return 0;
+}
+
+PRUnichar* nsCRT::strdup(const PRUnichar* str)
+{
+ PRUint32 len = nsCRT::strlen(str);
+ return strndup(str, len);
+}
+
+PRUnichar* nsCRT::strndup(const PRUnichar* str, PRUint32 len)
+{
+ nsCppSharedAllocator<PRUnichar> shared_allocator;
+ PRUnichar* rslt = shared_allocator.allocate(len + 1); // add one for the null
+ // PRUnichar* rslt = new PRUnichar[len + 1];
+
+ if (rslt == NULL) return NULL;
+ memcpy(rslt, str, len * sizeof(PRUnichar));
+ rslt[len] = 0;
+ return rslt;
+}
+
+ /**
+ * |nsCRT::HashCode| is identical to |PL_HashString|, which tests
+ * (http://bugzilla.mozilla.org/showattachment.cgi?attach_id=26596)
+ * show to be the best hash among several other choices.
+ *
+ * We re-implement it here rather than calling it for two reasons:
+ * (1) in this interface, we also calculate the length of the
+ * string being hashed; and (2) the narrow and wide and `buffer' versions here
+ * will hash equivalent strings to the same value, e.g., "Hello" and L"Hello".
+ */
+PRUint32 nsCRT::HashCode(const char* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const char* s = str;
+
+ if (!str) return h;
+
+ unsigned char c;
+ while ( (c = *s++) )
+ h = (h>>28) ^ (h<<4) ^ c;
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const PRUnichar* s = str;
+
+ if (!str) return h;
+
+ PRUnichar c;
+ while ( (c = *s++) )
+ h = (h>>28) ^ (h<<4) ^ c;
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const PRUnichar* s = str;
+
+ {
+ PRUint16 W1 = 0; // the first UTF-16 word in a two word tuple
+ PRUint32 U = 0; // the current char as UCS-4
+ int code_length = 0; // the number of bytes in the UTF-8 sequence for the current char
+
+ PRUint16 W;
+ while ( (W = *s++) )
+ {
+ /*
+ * On the fly, decoding from UTF-16 (and/or UCS-2) into UTF-8 as per
+ * http://www.ietf.org/rfc/rfc2781.txt
+ * http://www.ietf.org/rfc/rfc2279.txt
+ */
+
+ if ( !W1 )
+ {
+ if ( W < 0xD800 || 0xDFFF < W )
+ {
+ U = W;
+ if ( W <= 0x007F )
+ code_length = 1;
+ else if ( W <= 0x07FF )
+ code_length = 2;
+ else
+ code_length = 3;
+ }
+ else if ( /* 0xD800 <= W1 && */ W <= 0xDBFF )
+ W1 = W;
+ }
+ else
+ {
+ // as required by the standard, this code is careful to
+ // throw out illegal sequences
+
+ if ( 0xDC00 <= W && W <= 0xDFFF )
+ {
+ U = PRUint32( (W1&0x03FF)<<10 | (W&0x3FFF) );
+ if ( U <= 0x001FFFFF )
+ code_length = 4;
+ else if ( U <= 0x3FFFFFF )
+ code_length = 5;
+ else
+ code_length = 6;
+ }
+ W1 = 0;
+ }
+
+
+ if ( code_length > 0 )
+ {
+ static const PRUint16 sBytePrefix[7] = { 0x0000, 0x0000, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC };
+ static const PRUint16 sShift[7] = { 0, 0, 6, 12, 18, 24, 30 };
+
+ /*
+ * Unlike the algorithm in http://www.ietf.org/rfc/rfc2279.txt
+ * we must calculate the bytes in left to right order so that
+ * our hash result matches what the narrow version would calculate
+ * on an already UTF-8 string.
+ */
+
+ // hash the first (and often, only, byte)
+ h = (h>>28) ^ (h<<4) ^ (sBytePrefix[code_length] | (U>>sShift[code_length]));
+
+ // an unrolled loop for hashing any remaining bytes in this sequence
+ switch ( code_length )
+ { // falling through in each case
+ case 6: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>24) & 0x003F));
+ case 5: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>18) & 0x003F));
+ case 4: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>12) & 0x003F));
+ case 3: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>6 ) & 0x003F));
+ case 2: h = (h>>28) ^ (h<<4) ^ (0x80 | ( U & 0x003F));
+ default: code_length = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::BufferHashCode(const char* s, PRUint32 len)
+{
+ PRUint32 h = 0;
+ const char* done = s + len;
+
+ while ( s < done )
+ h = (h>>28) ^ (h<<4) ^ PRUint8(*s++); // cast to unsigned to prevent possible sign extension
+
+ return h;
+}
+
+PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len)
+{
+ PRUint32 h = 0;
+ const PRUnichar* done = s + len;
+
+ while ( s < done )
+ h = (h>>28) ^ (h<<4) ^ PRUint16(*s++); // cast to unsigned to prevent possible sign extension
+
+ return h;
+}
+
+// This should use NSPR but NSPR isn't exporting its PR_strtoll function
+// Until then...
+PRInt64 nsCRT::atoll(const char *str)
+{
+ if (!str)
+ return LL_Zero();
+
+ PRInt64 ll = LL_Zero(), digitll = LL_Zero();
+
+ while (*str && *str >= '0' && *str <= '9') {
+ LL_MUL(ll, ll, 10);
+ LL_UI2L(digitll, (*str - '0'));
+ LL_ADD(ll, ll, digitll);
+ str++;
+ }
+
+ return ll;
+}
+
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 04.27.2000
+ * @param aChar is character to be tested
+ * @return TRUE if in ASCII range
+ */
+PRBool nsCRT::IsAscii(PRUnichar aChar) {
+ return (0x0080 > aChar);
+}
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 10.02.2001
+ * @param aString is null terminated to be tested
+ * @return TRUE if all characters aare in ASCII range
+ */
+PRBool nsCRT::IsAscii(const PRUnichar *aString) {
+ while(*aString) {
+ if( 0x0080 <= *aString)
+ return PR_FALSE;
+ aString++;
+ }
+ return PR_TRUE;
+}
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 10.02.2001
+ * @param aString is null terminated to be tested
+ * @return TRUE if all characters aare in ASCII range
+ */
+PRBool nsCRT::IsAscii(const char *aString) {
+ while(*aString) {
+ if( 0x80 & *aString)
+ return PR_FALSE;
+ aString++;
+ }
+ return PR_TRUE;
+}
+/**
+ * Determine whether the given string consists of valid ascii chars
+ *
+ * @param aString is null terminated
+ * @param aLength is the number of chars to test. This must be at most
+ * the number of chars in aString before the null terminator
+ * @return PR_TRUE if all chars are valid ASCII chars, PR_FALSE otherwise
+ */
+PRBool nsCRT::IsAscii(const char* aString, PRUint32 aLength)
+{
+ const char* end = aString + aLength;
+ while (aString < end) {
+ NS_ASSERTION(*aString, "Null byte before end of data!");
+ if (0x80 & *aString)
+ return PR_FALSE;
+ ++aString;
+ }
+ return PR_TRUE;
+}
+
+/**
+ * Determine if given char in valid alpha range
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if in alpha range
+ */
+PRBool nsCRT::IsAsciiAlpha(PRUnichar aChar) {
+ // XXX i18n
+ if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/**
+ * Determine if given char is a valid space character
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if is valid space char
+ */
+PRBool nsCRT::IsAsciiSpace(PRUnichar aChar) {
+ // XXX i18n
+ if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+
+
+/**
+ * Determine if given char is valid digit
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if char is a valid digit
+ */
+PRBool nsCRT::IsAsciiDigit(PRUnichar aChar) {
+ // XXX i18n
+ return PRBool((aChar >= '0') && (aChar <= '9'));
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCRT.h b/src/libs/xpcom18a4/xpcom/ds/nsCRT.h
new file mode 100644
index 00000000..c168a0a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCRT.h
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsCRT_h___
+#define nsCRT_h___
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "plstr.h"
+#include "nscore.h"
+#include "prtypes.h"
+#include "nsCppSharedAllocator.h"
+
+#ifdef XP_MAC
+# define NS_LINEBREAK "\015"
+# define NS_LINEBREAK_LEN 1
+#else
+# if defined(XP_WIN) || defined(XP_OS2)
+# define NS_LINEBREAK "\015\012"
+# define NS_LINEBREAK_LEN 2
+# else
+# if defined(XP_UNIX) || defined(XP_BEOS)
+# define NS_LINEBREAK "\012"
+# define NS_LINEBREAK_LEN 1
+# endif /* XP_UNIX */
+# endif /* XP_WIN || XP_OS2 */
+#endif /* XP_MAC */
+
+extern const PRUnichar kIsoLatin1ToUCS2[256];
+
+// This macro can be used in a class declaration for classes that want
+// to ensure that their instance memory is zeroed.
+#define NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW \
+ void* operator new(size_t sz) CPP_THROW_NEW { \
+ void* rv = ::operator new(sz); \
+ if (rv) { \
+ memset(rv, 0, sz); \
+ } \
+ return rv; \
+ } \
+ void operator delete(void* ptr) { \
+ ::operator delete(ptr); \
+ }
+
+// This macro works with the next macro to declare a non-inlined
+// version of the above.
+#define NS_DECL_ZEROING_OPERATOR_NEW \
+ void* operator new(size_t sz) CPP_THROW_NEW; \
+ void operator delete(void* ptr);
+
+#define NS_IMPL_ZEROING_OPERATOR_NEW(_class) \
+ void* _class::operator new(size_t sz) CPP_THROW_NEW { \
+ void* rv = ::operator new(sz); \
+ if (rv) { \
+ memset(rv, 0, sz); \
+ } \
+ return rv; \
+ } \
+ void _class::operator delete(void* ptr) { \
+ ::operator delete(ptr); \
+ }
+
+// Freeing helper
+#define CRTFREEIF(x) if (x) { nsCRT::free(x); x = 0; }
+
+/// This is a wrapper class around all the C runtime functions.
+
+class NS_COM nsCRT {
+public:
+ enum {
+ TAB='\t' /* Horizontal Tab */,
+ LF='\n' /* Line Feed */,
+ VTAB='\v' /* Vertical Tab */,
+ FF='\f' /* Form Feed */,
+ CR='\r' /* Carriage Return */
+ };
+
+ /***
+ *** The following nsCRT::mem* functions are no longer
+ *** supported, please use the corresponding lib C
+ *** functions instead.
+ ***
+ *** nsCRT::memcpy()
+ *** nsCRT::memcmp()
+ *** nsCRT::memmove()
+ *** nsCRT::memset()
+ *** nsCRT::zero()
+ ***
+ *** Additionally, the following char* string utilities
+ *** are no longer supported, please use the
+ *** corresponding lib C functions instead.
+ ***
+ *** nsCRT::strlen()
+ ***
+ ***/
+
+ /** Compute the string length of s
+ @param s the string in question
+ @return the length of s
+ */
+ static PRUint32 strlen(const char* s) {
+ return PRUint32(::strlen(s));
+ }
+
+ /// Compare s1 and s2.
+ static PRInt32 strcmp(const char* s1, const char* s2) {
+ return PRInt32(PL_strcmp(s1, s2));
+ }
+
+ static PRInt32 strncmp(const char* s1, const char* s2,
+ PRUint32 aMaxLen) {
+ return PRInt32(PL_strncmp(s1, s2, aMaxLen));
+ }
+
+ /// Case-insensitive string comparison.
+ static PRInt32 strcasecmp(const char* s1, const char* s2) {
+ return PRInt32(PL_strcasecmp(s1, s2));
+ }
+
+ /// Case-insensitive string comparison with length
+ static PRInt32 strncasecmp(const char* s1, const char* s2, PRUint32 aMaxLen) {
+ PRInt32 result=PRInt32(PL_strncasecmp(s1, s2, aMaxLen));
+ //Egads. PL_strncasecmp is returning *very* negative numbers.
+ //Some folks expect -1,0,1, so let's temper its enthusiasm.
+ if (result<0)
+ result=-1;
+ return result;
+ }
+
+ static PRInt32 strncmp(const char* s1, const char* s2, PRInt32 aMaxLen) {
+ // inline the first test (assumes strings are not null):
+ PRInt32 diff = ((const unsigned char*)s1)[0] - ((const unsigned char*)s2)[0];
+ if (diff != 0) return diff;
+ return PRInt32(PL_strncmp(s1,s2,unsigned(aMaxLen)));
+ }
+
+ static char* strdup(const char* str) {
+ return PL_strdup(str);
+ }
+
+ static char* strndup(const char* str, PRUint32 len) {
+ return PL_strndup(str, len);
+ }
+
+ static void free(char* str) {
+ PL_strfree(str);
+ }
+
+ /**
+
+ How to use this fancy (thread-safe) version of strtok:
+
+ void main(void) {
+ printf("%s\n\nTokens:\n", string);
+ // Establish string and get the first token:
+ char* newStr;
+ token = nsCRT::strtok(string, seps, &newStr);
+ while (token != NULL) {
+ // While there are tokens in "string"
+ printf(" %s\n", token);
+ // Get next token:
+ token = nsCRT::strtok(newStr, seps, &newStr);
+ }
+ }
+ * WARNING - STRTOK WHACKS str THE FIRST TIME IT IS CALLED *
+ * MAKE A COPY OF str IF YOU NEED TO USE IT AFTER strtok() *
+ */
+ static char* strtok(char* str, const char* delims, char* *newStr);
+
+ /// Like strlen except for ucs2 strings
+ static PRUint32 strlen(const PRUnichar* s);
+
+ /// Like strcmp except for ucs2 strings
+ static PRInt32 strcmp(const PRUnichar* s1, const PRUnichar* s2);
+ /// Like strcmp except for ucs2 strings
+ static PRInt32 strncmp(const PRUnichar* s1, const PRUnichar* s2,
+ PRUint32 aMaxLen);
+
+ // You must use nsCRT::free(PRUnichar*) to free memory allocated
+ // by nsCRT::strdup(PRUnichar*).
+ static PRUnichar* strdup(const PRUnichar* str);
+
+ // You must use nsCRT::free(PRUnichar*) to free memory allocated
+ // by strndup(PRUnichar*, PRUint32).
+ static PRUnichar* strndup(const PRUnichar* str, PRUint32 len);
+
+ static void free(PRUnichar* str) {
+ nsCppSharedAllocator<PRUnichar> shared_allocator;
+ shared_allocator.deallocate(str, 0 /*we never new or kept the size*/);
+ }
+
+ // Computes the hashcode for a c-string, returns the string length as
+ // an added bonus.
+ static PRUint32 HashCode(const char* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes the hashcode for a ucs2 string, returns the string length
+ // as an added bonus.
+ static PRUint32 HashCode(const PRUnichar* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes a hashcode for a ucs2 string that returns the same thing
+ // as the HashCode method taking a |char*| would if the string were
+ // converted to UTF8. Returns the string length as an added bonus.
+ static PRUint32 HashCodeAsUTF8(const PRUnichar* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes the hashcode for a buffer with a specified length.
+ static PRUint32 BufferHashCode(const char* str, PRUint32 strLen);
+
+ // Computes the hashcode for a buffer with a specified length.
+ static PRUint32 BufferHashCode(const PRUnichar* str, PRUint32 strLen);
+
+ // String to longlong
+ static PRInt64 atoll(const char *str);
+
+ static char ToUpper(char aChar);
+
+ static char ToLower(char aChar);
+
+ static PRBool IsUpper(char aChar);
+
+ static PRBool IsLower(char aChar);
+
+ static PRBool IsAscii(PRUnichar aChar);
+ static PRBool IsAscii(const PRUnichar* aString);
+ static PRBool IsAsciiAlpha(PRUnichar aChar);
+ static PRBool IsAsciiDigit(PRUnichar aChar);
+ static PRBool IsAsciiSpace(PRUnichar aChar);
+ static PRBool IsAscii(const char* aString);
+ static PRBool IsAscii(const char* aString, PRUint32 aLength);
+};
+
+#define FF '\014'
+#define TAB '\011'
+
+#define CRSTR "\015"
+#define LFSTR "\012"
+#define CRLF "\015\012" /* A CR LF equivalent string */
+
+
+#if defined(XP_MAC)
+ #define FILE_PATH_SEPARATOR ":"
+ #define FILE_ILLEGAL_CHARACTERS ""
+#elif defined(XP_WIN) || defined(XP_OS2)
+ #define FILE_PATH_SEPARATOR "\\"
+ #define FILE_ILLEGAL_CHARACTERS "/:*?\"<>|"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ #define FILE_PATH_SEPARATOR "/"
+ #define FILE_ILLEGAL_CHARACTERS ""
+#else
+ #error need_to_define_your_file_path_separator_and_illegal_characters
+#endif
+
+#define NS_IS_SPACE(VAL) \
+ (((((intn)(VAL)) & 0x7f) == ((intn)(VAL))) && isspace((intn)(VAL)) )
+
+#define NS_IS_CNTRL(i) ((((unsigned int) (i)) > 0x7f) ? (int) 0 : iscntrl(i))
+#define NS_IS_DIGIT(i) ((((unsigned int) (i)) > 0x7f) ? (int) 0 : isdigit(i))
+#if defined(XP_WIN) || defined(XP_OS2)
+#define NS_IS_ALPHA(VAL) (isascii((int)(VAL)) && isalpha((int)(VAL)))
+#else
+#define NS_IS_ALPHA(VAL) ((((unsigned int) (VAL)) > 0x7f) ? (int) 0 : isalpha((int)(VAL)))
+#endif
+
+
+#endif /* nsCRT_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp
new file mode 100644
index 00000000..954de2d1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCheapSets.h"
+
+nsCheapStringSet::~nsCheapStringSet()
+{
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ delete set;
+ } else {
+ delete GetStr();
+ }
+}
+
+/**
+ * Put a string into the table
+ */
+nsresult
+nsCheapStringSet::Put(const nsAString& aVal)
+{
+ // Add the value to the hash if it is there
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ return set->Put(aVal);
+ }
+
+ // If a string is already there, create a hashtable and both of these to it
+ if (GetStr()) {
+ nsAString* oldStr = GetStr();
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = set->Put(*oldStr);
+ delete oldStr;
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Nothing exists in the hash right now, so just set the single string
+ return SetStr(aVal);
+}
+
+void
+nsCheapStringSet::Remove(const nsAString& aVal)
+{
+ // Remove from the hash if the hash is there
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ set->Remove(aVal);
+ return;
+ }
+
+ // Remove the string if there is just a string
+ nsAString* str = GetStr();
+ if (str && str->Equals(aVal)) {
+ delete str;
+ mValOrHash = nsnull;
+ }
+}
+
+nsresult
+nsCheapStringSet::InitHash(nsStringHashSet** aSet)
+{
+ nsStringHashSet* newSet = new nsStringHashSet();
+ if (!newSet) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = newSet->Init(10);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mValOrHash = newSet;
+ *aSet = newSet;
+ return NS_OK;
+}
+
+
+nsCheapInt32Set::~nsCheapInt32Set()
+{
+ delete GetHash();
+}
+
+nsresult
+nsCheapInt32Set::Put(PRInt32 aVal)
+{
+ // Add the value to the hash or set the pointer as an int
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ return set->Put(aVal);
+ }
+
+ // Create the hash and add the value to it if there is an int already
+ if (IsInt()) {
+ PRInt32 oldInt = GetInt();
+
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = set->Put(oldInt);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Create the hash anyway if the int is negative (negative numbers cannot
+ // fit into our PtrBits abstraction)
+ if (aVal < 0) {
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Finally, just set the int if we can't do anything with hashes
+ SetInt(aVal);
+ return NS_OK;
+}
+
+void
+nsCheapInt32Set::Remove(PRInt32 aVal)
+{
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ set->Remove(aVal);
+ } else if (IsInt() && GetInt() == aVal) {
+ mValOrHash = nsnull;
+ }
+}
+
+nsresult
+nsCheapInt32Set::InitHash(nsInt32HashSet** aSet)
+{
+ nsInt32HashSet* newSet = new nsInt32HashSet();
+ if (!newSet) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = newSet->Init(10);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mValOrHash = newSet;
+ *aSet = newSet;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h
new file mode 100644
index 00000000..7e1c917d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsCheapSets_h__
+#define __nsCheapSets_h__
+
+#include "nsHashSets.h"
+
+/**
+ * A string set that takes up minimal size when there are 0 or 1 strings in the
+ * set. Use for cases where sizes of 0 and 1 are even slightly common.
+ */
+class NS_COM nsCheapStringSet {
+public:
+ nsCheapStringSet() : mValOrHash(nsnull)
+ {
+ }
+ ~nsCheapStringSet();
+
+ /**
+ * Put a string into the set
+ * @param aVal the value to put in
+ */
+ nsresult Put(const nsAString& aVal);
+
+ /**
+ * Remove a string from the set
+ * @param aVal the string to remove
+ */
+ void Remove(const nsAString& aVal);
+
+ /**
+ * Check if the set contains a particular string
+ * @param aVal the string to check for
+ * @return whether the string is in the set
+ */
+ PRBool Contains(const nsAString& aVal)
+ {
+ nsStringHashSet* set = GetHash();
+ // Check the value from the hash if the hash is there
+ if (set) {
+ return set->Contains(aVal);
+ }
+
+ // Check whether the value is equal to the string if the string is there
+ nsAString* str = GetStr();
+ return str && str->Equals(aVal);
+ }
+
+private:
+ typedef PRUint64 PtrBits;
+
+ /** Get the hash pointer (or null if we're not a hash) */
+ nsStringHashSet* GetHash()
+ {
+ return (PtrBits(mValOrHash) & 0x1) ? nsnull : (nsStringHashSet*)mValOrHash;
+ }
+ /** Find out whether it is a string */
+ nsAString* GetStr()
+ {
+ return (PtrBits(mValOrHash) & 0x1)
+ ? (nsAString*)(PtrBits(mValOrHash) & ~0x1)
+ : nsnull;
+ }
+ /** Set the single string */
+ nsresult SetStr(const nsAString& aVal)
+ {
+ nsString* str = new nsString(aVal);
+ if (!str) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mValOrHash = (nsAString*)(PtrBits(str) | 0x1);
+ return NS_OK;
+ }
+ /** Initialize the hash */
+ nsresult InitHash(nsStringHashSet** aSet);
+
+private:
+ /** A hash or string ptr, depending on the lower bit (0=hash, 1=string) */
+ void* mValOrHash;
+};
+
+
+/**
+ * An integer set that takes up only 4 bytes when there are 0 or 1 integers
+ * in the set. Use for cases where sizes of 0 and 1 are even slightly common.
+ */
+class NS_COM nsCheapInt32Set {
+public:
+ nsCheapInt32Set() : mValOrHash(nsnull)
+ {
+ }
+ ~nsCheapInt32Set();
+
+ /**
+ * Put an int into the set
+ */
+ nsresult Put(PRInt32 aVal);
+
+ /**
+ * Remove a int from the set
+ * @param aVal the int to remove
+ */
+ void Remove(PRInt32 aVal);
+
+ /**
+ * Check if the set contains a particular int
+ * @param aVal the int to check for
+ * @return whether the int is in the set
+ */
+ PRBool Contains(PRInt32 aVal)
+ {
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ return set->Contains(aVal);
+ }
+ if (IsInt()) {
+ return GetInt() == aVal;
+ }
+ return PR_FALSE;
+ }
+
+private:
+ typedef PRUint64 PtrBits;
+
+ /** Get the hash pointer (or null if we're not a hash) */
+ nsInt32HashSet* GetHash()
+ {
+ return PtrBits(mValOrHash) & 0x1 ? nsnull : (nsInt32HashSet*)mValOrHash;
+ }
+ /** Find out whether it is an integer */
+ PRBool IsInt()
+ {
+ return !!(PtrBits(mValOrHash) & 0x1);
+ }
+ /** Get the single integer */
+ PRInt32 GetInt()
+ {
+ return PtrBits(mValOrHash) >> 1;
+ }
+ /** Set the single integer */
+ void SetInt(PRInt32 aInt)
+ {
+ mValOrHash = (void*)(uintptr_t)((aInt << 1) | 0x1);
+ }
+ /** Create the hash and initialize */
+ nsresult InitHash(nsInt32HashSet** aSet);
+
+private:
+ /** A hash or int, depending on the lower bit (0=hash, 1=int) */
+ void* mValOrHash;
+};
+
+
+/**
+ * XXX We may want an nsCheapVoidSet and nsCheapCStringSet at some point
+ */
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h
new file mode 100644
index 00000000..1fd73489
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsClassHashtable_h__
+#define nsClassHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsAutoPtr.h"
+
+/**
+ * templated hashtable class maps keys to C++ object pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Class the class-type being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class T>
+class nsClassHashtable :
+ public nsBaseHashtable< KeyClass, nsAutoPtr<T>, T* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef T* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData if the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+};
+
+
+/**
+ * Thread-safe version of nsClassHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Class the class-type being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class T>
+class nsClassHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsAutoPtr<T>, T* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef T* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData if the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+};
+
+
+//
+// nsClassHashtable definitions
+//
+
+template<class KeyClass,class T>
+PRBool
+nsClassHashtable<KeyClass,T>::Get(KeyType aKey, T** retVal) const
+{
+ typename nsBaseHashtable<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (retVal)
+ *retVal = ent->mData;
+
+ return PR_TRUE;
+ }
+
+ if (retVal)
+ *retVal = nsnull;
+
+ return PR_FALSE;
+}
+
+
+//
+// nsClassHashtableMT definitions
+//
+
+template<class KeyClass,class T>
+PRBool
+nsClassHashtableMT<KeyClass,T>::Get(KeyType aKey, T** retVal) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (retVal)
+ *retVal = ent->mData;
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ if (retVal)
+ *retVal = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsClassHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h
new file mode 100644
index 00000000..55f3e19d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h
@@ -0,0 +1,127 @@
+#ifndef nsCppSharedAllocator_h__
+#define nsCppSharedAllocator_h__
+
+#include "nsMemory.h" // for |nsMemory|
+#include "nscore.h" // for |NS_XXX_CAST|
+#include NEW_H // to allow placement |new|
+
+
+ // under Metrowerks (Mac), we don't have autoconf yet
+#ifdef __MWERKS__
+ #define HAVE_CPP_MEMBER_TEMPLATES
+ #define HAVE_CPP_NUMERIC_LIMITS
+#endif
+
+ // under MSVC shut off copious warnings about unused in-lines
+#ifdef _MSC_VER
+ #pragma warning( disable: 4514 )
+#endif
+
+#ifdef HAVE_CPP_NUMERIC_LIMITS
+#include <limits>
+#else
+#include <limits.h>
+#endif
+
+
+template <class T>
+class nsCppSharedAllocator
+ /*
+ ...allows Standard Library containers, et al, to use our global shared
+ (XP)COM-aware allocator.
+ */
+ {
+ public:
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef T* pointer;
+ typedef const T* const_pointer;
+
+ typedef T& reference;
+ typedef const T& const_reference;
+
+
+
+ nsCppSharedAllocator() { }
+
+#ifdef HAVE_CPP_MEMBER_TEMPLATES
+ template <class U>
+ nsCppSharedAllocator( const nsCppSharedAllocator<U>& ) { }
+#endif
+
+ ~nsCppSharedAllocator() { }
+
+
+ pointer
+ address( reference r ) const
+ {
+ return &r;
+ }
+
+ const_pointer
+ address( const_reference r ) const
+ {
+ return &r;
+ }
+
+ pointer
+ allocate( size_type n, const void* /*hint*/=0 )
+ {
+ return NS_REINTERPRET_CAST(pointer, nsMemory::Alloc(NS_STATIC_CAST(PRUint32, n*sizeof(T))));
+ }
+
+ void
+ deallocate( pointer p, size_type /*n*/ )
+ {
+ nsMemory::Free(p);
+ }
+
+ void
+ construct( pointer p, const T& val )
+ {
+ new (p) T(val);
+ }
+
+ void
+ destroy( pointer p )
+ {
+ p->~T();
+ }
+
+ size_type
+ max_size() const
+ {
+#ifdef HAVE_CPP_NUMERIC_LIMITS
+ return numeric_limits<size_type>::max() / sizeof(T);
+#else
+ return ULONG_MAX / sizeof(T);
+#endif
+ }
+
+#ifdef HAVE_CPP_MEMBER_TEMPLATES
+ template <class U>
+ struct rebind
+ {
+ typedef nsCppSharedAllocator<U> other;
+ };
+#endif
+ };
+
+
+template <class T>
+PRBool
+operator==( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
+ {
+ return PR_TRUE;
+ }
+
+template <class T>
+PRBool
+operator!=( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
+ {
+ return PR_FALSE;
+ }
+
+#endif /* !defined(nsCppSharedAllocator_h__) */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h
new file mode 100644
index 00000000..7a14f826
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDataHashtable_h__
+#define nsDataHashtable_h__
+
+#include "nsHashKeys.h"
+#include "nsBaseHashtable.h"
+
+/**
+ * templated hashtable class maps keys to simple datatypes.
+ * See nsBaseHashtable for complete declaration
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param DataType the simple datatype being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class DataType>
+class nsDataHashtable :
+ public nsBaseHashtable<KeyClass,DataType,DataType>
+{ };
+
+template<class KeyClass,class DataType>
+class nsDataHashtableMT :
+ public nsBaseHashtableMT<KeyClass,DataType,DataType>
+{ };
+
+#endif // nsDataHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp b/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp
new file mode 100644
index 00000000..d94568bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp
@@ -0,0 +1,627 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDeque.h"
+#include "nsCRT.h"
+#ifdef DEBUG_rickg
+#include <stdio.h>
+#endif
+
+/**
+ * 07/02/2001 09:17p 509,104 clangref.pdf from openwatcom's site
+ * Watcom C Language Reference Edition 11.0c
+ * page 118 of 297
+ *
+ * The % symbol yields the remainder from the division of the first operand
+ * by the second operand. The operands of % must have integral type.
+ *
+ * When both operands of % are positive, the result is a positive value
+ * smaller than the second operand. When one or both operands is negative,
+ * whether the result is positive or negative is implementation-defined.
+ *
+ */
+/* Ok, so first of all, C is underspecified. joy.
+ * The following functions do not provide a correct implementation of modulus
+ * They provide functionality for x>-y.
+ * There are risks of 2*y being greater than max int, which is part of the
+ * reason no multiplication is used and other operations are avoided.
+ *
+ * modasgn
+ * @param x variable
+ * @param y expression
+ * approximately equivalent to x %= y
+ *
+ * modulus
+ * @param x expression
+ * @param y expression
+ * approximately equivalent to x % y
+ */
+#define modasgn(x,y) if (x<0) x+=y; x%=y
+#define modulus(x,y) ((x<0)?(x+y)%(y):(x)%(y))
+
+MOZ_DECL_CTOR_COUNTER(nsDeque)
+
+/**
+ * Standard constructor
+ * @param deallocator, called by Erase and ~nsDeque
+ */
+nsDeque::nsDeque(nsDequeFunctor* aDeallocator) {
+ MOZ_COUNT_CTOR(nsDeque);
+ mDeallocator=aDeallocator;
+ mOrigin=mSize=0;
+ mData=mBuffer; // don't allocate space until you must
+ mCapacity=sizeof(mBuffer)/sizeof(mBuffer[0]);
+ memset(mData, 0, mCapacity*sizeof(mBuffer[0]));
+}
+
+/**
+ * Destructor
+ */
+nsDeque::~nsDeque() {
+ MOZ_COUNT_DTOR(nsDeque);
+
+#ifdef DEBUG_rickg
+ char buffer[30];
+ printf("Capacity: %i\n", mCapacity);
+
+ static int mCaps[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ switch(mCapacity) {
+ case 4: mCaps[0]++; break;
+ case 8: mCaps[1]++; break;
+ case 16: mCaps[2]++; break;
+ case 32: mCaps[3]++; break;
+ case 64: mCaps[4]++; break;
+ case 128: mCaps[5]++; break;
+ case 256: mCaps[6]++; break;
+ case 512: mCaps[7]++; break;
+ case 1024: mCaps[8]++; break;
+ case 2048: mCaps[9]++; break;
+ case 4096: mCaps[10]++; break;
+ default:
+ break;
+ }
+#endif
+
+ Erase();
+ if (mData && (mData!=mBuffer)) {
+ delete [] mData;
+ }
+ mData=0;
+ SetDeallocator(0);
+}
+
+/**
+ * Set the functor to be called by Erase()
+ * The deque owns the functor.
+ *
+ * @param aDeallocator functor object for use by Erase()
+ */
+void nsDeque::SetDeallocator(nsDequeFunctor* aDeallocator){
+ if (mDeallocator) {
+ delete mDeallocator;
+ }
+ mDeallocator=aDeallocator;
+}
+
+/**
+ * Remove all items from container without destroying them.
+ *
+ * @return *this
+ */
+nsDeque& nsDeque::Empty() {
+ if (mSize && mData) {
+ memset(mData, 0, mCapacity*sizeof(*mData));
+ }
+ mSize=0;
+ mOrigin=0;
+ return *this;
+}
+
+/**
+ * Remove and delete all items from container
+ *
+ * @return *this
+ */
+nsDeque& nsDeque::Erase() {
+ if (mDeallocator && mSize) {
+ ForEach(*mDeallocator);
+ }
+ return Empty();
+}
+
+/**
+ * This method quadruples the size of the deque
+ * Elements in the deque are resequenced so that elements
+ * in the deque are stored sequentially
+ *
+ * If the deque actually overflows, there's very little we can do.
+ * Perhaps this function should return PRBool/nsresult indicating success/failure.
+ *
+ * @return capacity of the deque
+ * If the deque did not grow,
+ * and you knew its capacity beforehand,
+ * then this would be a way to indicate the failure.
+ */
+PRInt32 nsDeque::GrowCapacity() {
+ PRInt32 theNewSize=mCapacity<<2;
+ NS_ASSERTION(theNewSize>mCapacity, "Overflow");
+ if (theNewSize<=mCapacity)
+ return mCapacity;
+ void** temp=new void*[theNewSize];
+
+ //Here's the interesting part: You can't just move the elements
+ //directly (in situ) from the old buffer to the new one.
+ //Since capacity has changed, the old origin doesn't make
+ //sense anymore. It's better to resequence the elements now.
+
+ if (temp) {
+ PRInt32 tempi=0;
+ PRInt32 i=0;
+ PRInt32 j=0;
+ for (i=mOrigin; i<mCapacity; i++) {
+ temp[tempi++]=mData[i]; //copy the leading elements...
+ }
+ for (j=0;j<mOrigin;j++) {
+ temp[tempi++]=mData[j]; //copy the trailing elements...
+ }
+ if (mData != mBuffer) {
+ delete [] mData;
+ }
+ mCapacity=theNewSize;
+ mOrigin=0; //now realign the origin...
+ mData=temp;
+ }
+ return mCapacity;
+}
+
+/**
+ * This method adds an item to the end of the deque.
+ * This operation has the potential to cause the
+ * underlying buffer to resize.
+ *
+ * @param aItem: new item to be added to deque
+ * @return *this
+ */
+nsDeque& nsDeque::Push(void* aItem) {
+ if (mSize==mCapacity) {
+ GrowCapacity();
+ }
+ mData[modulus(mOrigin + mSize, mCapacity)]=aItem;
+ mSize++;
+ return *this;
+}
+
+/**
+ * This method adds an item to the front of the deque.
+ * This operation has the potential to cause the
+ * underlying buffer to resize.
+ *
+ * --Commments for GrowCapacity() case
+ * We've grown and shifted which means that the old
+ * final element in the deque is now the first element
+ * in the deque. This is temporary.
+ * We haven't inserted the new element at the front.
+ *
+ * To continue with the idea of having the front at zero
+ * after a grow, we move the old final item (which through
+ * the voodoo of mOrigin-- is now the first) to its final
+ * position which is conveniently the old length.
+ *
+ * Note that this case only happens when the deque is full.
+ * [And that pieces of this magic only work if the deque is full.]
+ * picture:
+ * [ABCDEFGH] @[mOrigin:3]:D.
+ * Task: PushFront("Z")
+ * shift mOrigin so, @[mOrigin:2]:C
+ * stretch and rearrange: (mOrigin:0)
+ * [CDEFGHAB ________ ________ ________]
+ * copy: (The second C is currently out of bounds)
+ * [CDEFGHAB C_______ ________ ________]
+ * later we will insert Z:
+ * [ZDEFGHAB C_______ ________ ________]
+ * and increment size: 9. (C is no longer out of bounds)
+ * --
+ * @param aItem: new item to be added to deque
+ * @return *this
+ */
+nsDeque& nsDeque::PushFront(void* aItem) {
+ mOrigin--;
+ modasgn(mOrigin,mCapacity);
+ if (mSize==mCapacity) {
+ GrowCapacity();
+ /* Comments explaining this are above*/
+ mData[mSize]=mData[mOrigin];
+ }
+ mData[mOrigin]=aItem;
+ mSize++;
+ return *this;
+}
+
+/**
+ * Remove and return the last item in the container.
+ *
+ * @return ptr to last item in container
+ */
+void* nsDeque::Pop() {
+ void* result=0;
+ if (mSize>0) {
+ --mSize;
+ PRInt32 offset=modulus(mSize + mOrigin, mCapacity);
+ result=mData[offset];
+ mData[offset]=0;
+ if (!mSize) {
+ mOrigin=0;
+ }
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to remove and return
+ * the first member in the container.
+ *
+ * @return last item in container
+ */
+void* nsDeque::PopFront() {
+ void* result=0;
+ if (mSize>0) {
+ NS_ASSERTION(mOrigin < mCapacity, "Error: Bad origin");
+ result=mData[mOrigin];
+ mData[mOrigin++]=0; //zero it out for debugging purposes.
+ mSize--;
+ // Cycle around if we pop off the end
+ // and reset origin if when we pop the last element
+ if (mCapacity==mOrigin || !mSize) {
+ mOrigin=0;
+ }
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to peek at the bottom
+ * member without removing it.
+ *
+ * @return last item in container
+ */
+void* nsDeque::Peek() {
+ void* result=0;
+ if (mSize>0) {
+ result = mData[modulus(mSize - 1 + mOrigin, mCapacity)];
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to peek at the topmost
+ * member without removing it.
+ *
+ * @return last item in container
+ */
+void* nsDeque::PeekFront() {
+ void* result=0;
+ if (mSize>0) {
+ result=mData[mOrigin];
+ }
+ return result;
+}
+
+/**
+ * Call this to retrieve the ith element from this container.
+ * Keep in mind that accessing the underlying elements is
+ * done in a relative fashion. Object 0 is not necessarily
+ * the first element (the first element is at mOrigin).
+ *
+ * @param aIndex : 0 relative offset of item you want
+ * @return void* or null
+ */
+void* nsDeque::ObjectAt(PRInt32 aIndex) const {
+ void* result=0;
+ if ((aIndex>=0) && (aIndex<mSize)) {
+ result=mData[modulus(mOrigin + aIndex, mCapacity)];
+ }
+ return result;
+}
+
+/**
+ * Create and return an iterator pointing to
+ * the beginning of the queue. Note that this
+ * takes the circular buffer semantics into account.
+ *
+ * @return new deque iterator, init'ed to 1st item
+ */
+nsDequeIterator nsDeque::Begin() const{
+ return nsDequeIterator(*this, 0);
+}
+
+/**
+ * Create and return an iterator pointing to
+ * the last item in the deque.
+ * Note that this takes the circular buffer semantics
+ * into account.
+ *
+ * @return new deque iterator, init'ed to the last item
+ */
+nsDequeIterator nsDeque::End() const{
+ return nsDequeIterator(*this, mSize - 1);
+}
+
+void* nsDeque::Last() const {
+ return End().GetCurrent();
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+void nsDeque::ForEach(nsDequeFunctor& aFunctor) const{
+ for (PRInt32 i=0; i<mSize; i++) {
+ aFunctor(ObjectAt(i));
+ }
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+const void* nsDeque::FirstThat(nsDequeFunctor& aFunctor) const{
+ for (PRInt32 i=0; i<mSize; i++) {
+ void* obj=aFunctor(ObjectAt(i));
+ if (obj) {
+ return obj;
+ }
+ }
+ return 0;
+}
+
+/******************************************************
+ * Here comes the nsDequeIterator class...
+ ******************************************************/
+
+/**
+ * DequeIterator is an object that knows how to iterate (forward and backward)
+ * through a Deque. Normally, you don't need to do this, but there are some special
+ * cases where it is pretty handy, so here you go.
+ *
+ * This is a standard dequeiterator constructor
+ *
+ * @param aQueue is the deque object to be iterated
+ * @param aIndex is the starting position for your iteration
+ */
+nsDequeIterator::nsDequeIterator(const nsDeque& aQueue, int aIndex)
+: mIndex(aIndex),
+ mDeque(aQueue)
+{
+}
+
+/**
+ * Create a copy of a DequeIterator
+ *
+ * @param aCopy is another iterator to copy from
+ */
+nsDequeIterator::nsDequeIterator(const nsDequeIterator& aCopy)
+: mIndex(aCopy.mIndex),
+ mDeque(aCopy.mDeque)
+{
+}
+
+/**
+ * Moves iterator to first element in deque
+ * @return *this
+ */
+nsDequeIterator& nsDequeIterator::First(){
+ mIndex=0;
+ return *this;
+}
+
+/**
+ * Standard assignment operator for dequeiterator
+ *
+ * @param aCopy is an iterator to be copied from
+ * @return *this
+ */
+nsDequeIterator& nsDequeIterator::operator=(const nsDequeIterator& aCopy) {
+ NS_ASSERTION(&mDeque==&aCopy.mDeque,"you can't change the deque that an interator is iterating over, sorry.");
+ mIndex=aCopy.mIndex;
+ return *this;
+}
+
+/**
+ * preform ! operation against to iterators to test for equivalence
+ * (or lack thereof)!
+ *
+ * @param aIter is the object to be compared to
+ * @return TRUE if NOT equal.
+ */
+PRBool nsDequeIterator::operator!=(nsDequeIterator& aIter) {
+ return PRBool(!this->operator==(aIter));
+}
+
+/**
+ * Compare two iterators for increasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to an element before
+ * the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over the same deque.
+ */
+PRBool nsDequeIterator::operator<(nsDequeIterator& aIter) {
+ return PRBool(((mIndex<aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Compare two iterators for equivalence.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if EQUAL
+ */
+PRBool nsDequeIterator::operator==(nsDequeIterator& aIter) {
+ return PRBool(((mIndex==aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Compare two iterators for non strict decreasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to the same element, or
+ * an element after the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over the same deque.
+ */
+PRBool nsDequeIterator::operator>=(nsDequeIterator& aIter) {
+ return PRBool(((mIndex>=aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Pre-increment operator
+ *
+ * @return object at post-incremented index
+ */
+void* nsDequeIterator::operator++() {
+ NS_ASSERTION(mIndex<mDeque.mSize,
+ "You have reached the end of the Internet."\
+ "You have seen everything there is to see. Please go back. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>=mDeque.mSize) return 0;
+#endif
+ return mDeque.ObjectAt(++mIndex);
+}
+
+/**
+ * Post-increment operator
+ *
+ * @param param is ignored
+ * @return object at pre-incremented index
+ */
+void* nsDequeIterator::operator++(int) {
+ NS_ASSERTION(mIndex<=mDeque.mSize,
+ "You have already reached the end of the Internet."\
+ "You have seen everything there is to see. Please go back. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>mDeque.mSize) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex++);
+}
+
+/**
+ * Pre-decrement operator
+ *
+ * @return object at pre-decremented index
+ */
+void* nsDequeIterator::operator--() {
+ NS_ASSERTION(mIndex>=0,
+ "You have reached the beginning of the Internet."\
+ "You have seen everything there is to see. Please go forward. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(--mIndex);
+}
+
+/**
+ * Post-decrement operator
+ *
+ * @param param is ignored
+ * @return object at post-decremented index
+ */
+void* nsDequeIterator::operator--(int) {
+ NS_ASSERTION(mIndex>=0,
+ "You have already reached the beginning of the Internet."\
+ "You have seen everything there is to see. Please go forward. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex--);
+}
+
+/**
+ * Dereference operator
+ * Note that the iterator floats, so you don't need to do:
+ * <code>++iter; aDeque.PopFront();</code>
+ * Unless you actually want your iterator to jump 2 spaces.
+ *
+ * Picture: [1 2I 3 4]
+ * PopFront()
+ * Picture: [2 3I 4]
+ * Note that I still happily points to object at the second index
+ *
+ * @return object at ith index
+ */
+void* nsDequeIterator::GetCurrent() {
+ NS_ASSERTION(mIndex<mDeque.mSize&&mIndex>=0,"Current is out of bounds");
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>=mDeque.mSize||mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex);
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{
+ mDeque.ForEach(aFunctor);
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{
+ return mDeque.FirstThat(aFunctor);
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDeque.h b/src/libs/xpcom18a4/xpcom/ds/nsDeque.h
new file mode 100644
index 00000000..7fdf7465
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDeque.h
@@ -0,0 +1,405 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * MODULE NOTES:
+ *
+ * The Deque is a very small, very efficient container object
+ * than can hold elements of type void*, offering the following features:
+ * Its interface supports pushing and popping of elements.
+ * It can iterate (via an interator class) its elements.
+ * When full, it can efficiently resize dynamically.
+ *
+ *
+ * NOTE: The only bit of trickery here is that this deque is
+ * built upon a ring-buffer. Like all ring buffers, the first
+ * element may not be at index[0]. The mOrigin member determines
+ * where the first child is. This point is quietly hidden from
+ * customers of this class.
+ *
+ */
+
+#ifndef _NSDEQUE
+#define _NSDEQUE
+
+#include "nscore.h"
+
+/**
+ * The nsDequeFunctor class is used when you want to create
+ * callbacks between the deque and your generic code.
+ * Use these objects in a call to ForEach();
+ *
+ */
+
+class nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject)=0;
+};
+
+/******************************************************
+ * Here comes the nsDeque class itself...
+ ******************************************************/
+
+/**
+ * The deque (double-ended queue) class is a common container type,
+ * whose behavior mimics a line in your favorite checkout stand.
+ * Classic CS describes the common behavior of a queue as FIFO.
+ * A deque allows insertion and removal at both ends of
+ * the container.
+ *
+ * The deque stores pointers to items.
+ */
+
+class nsDequeIterator;
+
+class NS_COM nsDeque {
+ friend class nsDequeIterator;
+ public:
+ nsDeque(nsDequeFunctor* aDeallocator);
+ ~nsDeque();
+
+ /**
+ * Returns the number of elements currently stored in
+ * this deque.
+ *
+ * @return number of elements currently in the deque
+ */
+ inline PRInt32 GetSize() const {return mSize;}
+
+ /**
+ * Appends new member at the end of the deque.
+ *
+ * @param item to store in deque
+ * @return *this
+ */
+ nsDeque& Push(void* aItem);
+
+ /**
+ * Inserts new member at the front of the deque.
+ *
+ * @param item to store in deque
+ * @return *this
+ */
+ nsDeque& PushFront(void* aItem);
+
+ /**
+ * Remove and return the last item in the container.
+ *
+ * @return the item that was the last item in container
+ */
+ void* Pop();
+
+ /**
+ * Remove and return the first item in the container.
+ *
+ * @return the item that was first item in container
+ */
+ void* PopFront();
+
+ /**
+ * Retrieve the bottom item without removing it.
+ *
+ * @return the first item in container
+ */
+
+ void* Peek();
+ /**
+ * Return topmost item without removing it.
+ *
+ * @return the first item in container
+ */
+ void* PeekFront();
+
+ /**
+ * Retrieve the i'th member from the deque without removing it.
+ *
+ * @param index of desired item
+ * @return i'th element in list
+ */
+ void* ObjectAt(int aIndex) const;
+
+ /**
+ * Remove all items from container without destroying them.
+ *
+ * @return *this
+ */
+ nsDeque& Empty();
+
+ /**
+ * Remove and delete all items from container.
+ * Deletes are handled by the deallocator nsDequeFunctor
+ * which is specified at deque construction.
+ *
+ * @return *this
+ */
+ nsDeque& Erase();
+
+ /**
+ * Creates a new iterator, pointing to the first
+ * item in the deque.
+ *
+ * @return new dequeIterator
+ */
+ nsDequeIterator Begin() const;
+
+ /**
+ * Creates a new iterator, pointing to the last
+ * item in the deque.
+ *
+ * @return new dequeIterator
+ */
+ nsDequeIterator End() const;
+
+ void* Last() const;
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+ void ForEach(nsDequeFunctor& aFunctor) const;
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+ const void* FirstThat(nsDequeFunctor& aFunctor) const;
+
+ void SetDeallocator(nsDequeFunctor* aDeallocator);
+
+protected:
+ PRInt32 mSize;
+ PRInt32 mCapacity;
+ PRInt32 mOrigin;
+ nsDequeFunctor* mDeallocator;
+ void* mBuffer[8];
+ void** mData;
+
+private:
+
+ /**
+ * Simple default constructor (PRIVATE)
+ */
+ nsDeque();
+
+ /**
+ * Copy constructor (PRIVATE)
+ *
+ * @param another deque
+ */
+ nsDeque(const nsDeque& other);
+
+ /**
+ * Deque assignment operator (PRIVATE)
+ *
+ * @param another deque
+ * @return *this
+ */
+ nsDeque& operator=(const nsDeque& anOther);
+
+ PRInt32 GrowCapacity();
+};
+
+/******************************************************
+ * Here comes the nsDequeIterator class...
+ ******************************************************/
+
+class nsDequeIterator {
+public:
+ /**
+ * DequeIterator is an object that knows how to iterate
+ * (forward and backward) through a Deque. Normally,
+ * you don't need to do this, but there are some special
+ * cases where it is pretty handy.
+ *
+ * One warning: the iterator is not bound to an item,
+ * it is bound to an index, so if you insert or remove
+ * from the beginning while using an iterator
+ * (which is not recommended) then the iterator will
+ * point to a different item. @see GetCurrent()
+ *
+ * Here you go.
+ *
+ * @param aQueue is the deque object to be iterated
+ * @param aIndex is the starting position for your iteration
+ */
+ nsDequeIterator(const nsDeque& aQueue, int aIndex=0);
+
+ /**
+ * Create a copy of a DequeIterator
+ *
+ * @param aCopy is another iterator to copy from
+ */
+ nsDequeIterator(const nsDequeIterator& aCopy);
+
+ /**
+ * Moves iterator to first element in the deque
+ * @return *this
+ */
+ nsDequeIterator& First();
+
+ /**
+ * Standard assignment operator for dequeiterator
+ * @param aCopy is another iterator to copy from
+ * @return *this
+ */
+ nsDequeIterator& operator=(const nsDequeIterator& aCopy);
+
+ /**
+ * preform ! operation against two iterators to test for equivalence
+ * (or lack thereof)!
+ *
+ * @param aIter is the object to be compared to
+ * @return TRUE if NOT equal.
+ */
+ PRBool operator!=(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for increasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to an element before
+ * the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over
+ * the same deque.
+ */
+ PRBool operator<(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for equivalence.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if EQUAL
+ */
+ PRBool operator==(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for non strict decreasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to the same element, or
+ * an element after the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over
+ * the same deque.
+ */
+ PRBool operator>=(nsDequeIterator& aIter);
+
+ /**
+ * Pre-increment operator
+ * Iterator will advance one index towards the end.
+ *
+ * @return object_at(++index)
+ */
+ void* operator++();
+
+ /**
+ * Post-increment operator
+ * Iterator will advance one index towards the end.
+ *
+ * @param param is ignored
+ * @return object_at(mIndex++)
+ */
+ void* operator++(int);
+
+ /**
+ * Pre-decrement operator
+ * Iterator will advance one index towards the beginning.
+ *
+ * @return object_at(--index)
+ */
+ void* operator--();
+
+ /**
+ * Post-decrement operator
+ * Iterator will advance one index towards the beginning.
+ *
+ * @param param is ignored
+ * @return object_at(index--)
+ */
+ void* operator--(int);
+
+ /**
+ * Retrieve the the iterator's notion of current node.
+ *
+ * Note that the iterator floats, so you don't need to do:
+ * <code>++iter; aDeque.PopFront();</code>
+ * Unless you actually want your iterator to jump 2 positions
+ * relative to its origin.
+ *
+ * Picture: [1 2i 3 4]
+ * PopFront()
+ * Picture: [2 3i 4]
+ * Note that I still happily points to object at the second index.
+ *
+ * @return object at i'th index
+ */
+ void* GetCurrent();
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+ void ForEach(nsDequeFunctor& aFunctor) const;
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+ const void* FirstThat(nsDequeFunctor& aFunctor) const;
+
+ protected:
+
+ PRInt32 mIndex;
+ const nsDeque& mDeque;
+};
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h
new file mode 100644
index 00000000..27bf4ce5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * nsDoubleHashtable.h is OBSOLETE. Use nsTHashtable or a derivative instead.
+ */
+
+#ifndef __nsDoubleHashtable_h__
+#define __nsDoubleHashtable_h__
+
+#include "pldhash.h"
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/*
+ * This file provides several major things to make PLDHashTable easier to use:
+ * - hash class macros for you to define a hashtable
+ * - default key classes to use as superclasses for your entries
+ * - empty maps for string, cstring, int and void
+ */
+
+/*
+ * USAGE
+ *
+ * To use nsDoubleHashtable macros
+ * (1) Define an entry class
+ * (2) Create the hash class
+ * (3) Use the hash class
+ *
+ * EXAMPLE
+ *
+ * As an example, let's create a dictionary, a mapping from a string (the word)
+ * to the pronunciation and definition of those words.
+ *
+ * (1) Define an entry class
+ *
+ * What we want here is an entry class that contains the word, the
+ * pronunciation string, and the definition string. Since we have a string key
+ * we can use the standard PLDHashStringEntry class as our base, it will handle
+ * the key stuff for us automatically.
+ *
+ * #include "nsDoubleHashtable.h"
+ *
+ * // Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY. Everything will break.
+ * // This is because of the 4-byte pointer C++ magically prepends onto your
+ * // entry class. It interacts very unhappily with PLDHashTable.
+ * class DictionaryEntry : public PLDHashStringEntry {
+ * public:
+ * DictionaryEntry(const void* aKey) : PLDHashStringEntry(aKey) { }
+ * ~DictionaryEntry() { }
+ * nsString mPronunciation;
+ * nsString mDefinition;
+ * }
+ *
+ * (2) Create the hash class
+ *
+ * The final hash class you will use in step 3 is defined by 2 macros.
+ *
+ * DECL_DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
+ * DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
+ *
+ * (3) Use the hash class
+ *
+ * Here is a simple main() that might look up a string:
+ *
+ * int main(void) {
+ * Dictionary d;
+ * nsresult rv = d.Init(10);
+ * if (NS_FAILED(rv)) return 1;
+ *
+ * // Put an entry
+ * DictionaryEntry* a = d.AddEntry(NS_LITERAL_STRING("doomed"));
+ * if (!a) return 1;
+ * a->mDefinition.AssignLiteral("The state you get in when a Mozilla release is pending");
+ * a->mPronunciation.AssignLiteral("doom-d");
+ *
+ * // Get the entry
+ * DictionaryEntry* b = d.GetEntry(NS_LITERAL_STRING("doomed"));
+ * printf("doomed: %s\n", NS_ConvertUCS2toUTF8(b->mDefinition).get());
+ *
+ * // Entries will be automagically cleaned up when the Dictionary object goes away
+ * return 0;
+ * }
+ *
+ *
+ * BONUS POINTS
+ *
+ * You may wish to extend this class and add helper functions like
+ * nsDependentString* GetDefinition(nsAString& aWord). For example:
+ *
+ * class MyDictionary : public Dictionary {
+ * public:
+ * MyDictionary() { }
+ * // Make SURE you have a virtual destructor
+ * virtual ~myDictionary() { }
+ * nsDependentString* GetDefinition(const nsAString& aWord) {
+ * DictionaryEntry* e = GetEntry(aWord);
+ * if (e) {
+ * // We're returning an nsDependentString here, callers need to delete it
+ * // and it doesn't last long, but at least it doesn't create a copy
+ * return new nsDependentString(e->mDefinition.get());
+ * } else {
+ * return nsnull;
+ * }
+ * }
+ * nsresult PutDefinition(const nsAString& aWord,
+ * const nsAString& aDefinition,
+ * const nsAString& aPronunciation) {
+ * DictionaryEntry* e = AddEntry(aWord);
+ * if (!e) {
+ * return NS_ERROR_OUT_OF_MEMORY;
+ * }
+ * e->mDefinition = aDefinition;
+ * e->mPronunciation = aPronunciation;
+ * return NS_OK;
+ * }
+ * }
+ */
+
+/*
+ * ENTRY CLASS DEFINITION
+ *
+ * The simplifications of PLDHashTable all hinge upon the idea of an entry
+ * class, which is a class you define, where you store the key and values that
+ * you will place in each hash entry. You must define six methods for an entry
+ * (the standard key classes, which you can extend from, define all of these
+ * for you except the constructor and destructor):
+ *
+ * CONSTRUCTOR(const void* aKey)
+ * When your entry is constructed it will only be given a pointer to the key.
+ *
+ * DESTRUCTOR
+ * Called when the entry is destroyed (of course).
+ *
+ * const void* GetKey()
+ * Must return a pointer to the key
+ *
+ * PRBool MatchEntry(const void* aKey) - return true or false depending on
+ * whether the key pointed to by aKey matches this entry
+ *
+ * static PLDHashNumber HashKey(const void* aKey) - get a hashcode based on the
+ * key (must be the same every time for the same key, but does not have
+ * to be unique)
+ *
+ * For a small hash that just does key->value, you will often just extend a
+ * standard key class and put a value member into it, and have a destructor and
+ * constructor--nothing else necessary.
+ *
+ * See the default key entry classes as example entry classes.
+ *
+ * NOTES:
+ * - Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY. Everything will break.
+ * This is because of the 4-byte pointer C++ magically prepends onto your
+ * entry class. It interacts very unhappily with PLDHashTable.
+ */
+
+/*
+ * PRIVATE HASHTABLE MACROS
+ *
+ * These internal macros can be used to declare the callbacks for an entry
+ * class, but the wrapper class macros call these for you so don't call them.
+ */
+
+//
+// DHASH_CALLBACKS
+//
+// Define the hashtable callback functions. Do this in one place only, as you
+// will have redundant symbols otherwise.
+//
+// ENTRY_CLASS: the classname of the entry
+//
+#define DHASH_CALLBACKS(ENTRY_CLASS) \
+PR_STATIC_CALLBACK(const void *) \
+ENTRY_CLASS##GetKey(PLDHashTable* table, PLDHashEntryHdr* entry) \
+{ \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*, entry); \
+ return e->GetKey(); \
+} \
+PR_STATIC_CALLBACK(PLDHashNumber) \
+ENTRY_CLASS##HashKey(PLDHashTable* table, const void* key) \
+{ \
+ return ENTRY_CLASS::HashKey(key); \
+} \
+PR_STATIC_CALLBACK(PRBool) \
+ENTRY_CLASS##MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, \
+ const void *key) \
+{ \
+ const ENTRY_CLASS* e = NS_STATIC_CAST(const ENTRY_CLASS*, entry); \
+ return e->MatchEntry(key); \
+} \
+PR_STATIC_CALLBACK(void) \
+ENTRY_CLASS##ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) \
+{ \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS *, entry); \
+ e->~ENTRY_CLASS(); \
+} \
+PR_STATIC_CALLBACK(PRBool) \
+ENTRY_CLASS##InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, \
+ const void *key) \
+{ \
+ new (entry) ENTRY_CLASS(key); \
+ return PR_TRUE; \
+}
+
+//
+// DHASH_INIT
+//
+// Initialize hashtable to a certain class.
+//
+// HASHTABLE: the name of the PLDHashTable variable
+// ENTRY_CLASS: the classname of the entry
+// NUM_INITIAL_ENTRIES: the number of entry slots the hashtable should start
+// with
+// RV: an nsresult variable to hold the outcome of the initialization.
+// Will be NS_ERROR_OUT_OF_MEMORY if failed, NS_OK otherwise.
+//
+#define DHASH_INIT(HASHTABLE,ENTRY_CLASS,NUM_INITIAL_ENTRIES,RV) \
+PR_BEGIN_MACRO \
+ static PLDHashTableOps hash_table_ops = \
+ { \
+ PL_DHashAllocTable, \
+ PL_DHashFreeTable, \
+ ENTRY_CLASS##GetKey, \
+ ENTRY_CLASS##HashKey, \
+ ENTRY_CLASS##MatchEntry, \
+ PL_DHashMoveEntryStub, \
+ ENTRY_CLASS##ClearEntry, \
+ PL_DHashFinalizeStub, \
+ ENTRY_CLASS##InitEntry \
+ }; \
+ PRBool isLive = PL_DHashTableInit(&(HASHTABLE), \
+ &hash_table_ops, nsnull, \
+ sizeof(ENTRY_CLASS), \
+ (NUM_INITIAL_ENTRIES)); \
+ if (!isLive) { \
+ (HASHTABLE).ops = nsnull; \
+ RV = NS_ERROR_OUT_OF_MEMORY; \
+ } else { \
+ RV = NS_OK; \
+ } \
+PR_END_MACRO
+
+
+/*
+ * WRAPPER CLASS
+ *
+ * This class handles initialization and destruction of the hashtable
+ * (you must call Init() yourself). It defines these functions:
+ *
+ * Init(aNumInitialEntries)
+ * Initialize the hashtable. This must be called once, it is only separate
+ * from the constructor so that you can get the return value. You should pass
+ * in the number of entries you think the hashtable will typically hold (this
+ * will be the amount of space allocated initially so that it will not have to
+ * grow).
+ *
+ * ENTRY_CLASS* GetEntry(aKey):
+ * Get the entry referenced by aKey and return a pointer to it. THIS IS A
+ * TEMPORARY POINTER and is only guaranteed to exist until the next time you do
+ * an operation on the hashtable. But you can safely use it until then.
+ *
+ * Returns nsnull if the entry is not found.
+ *
+ * ENTRY_CLASS* AddEntry(aKey):
+ * Create a new, empty entry and return a pointer to it for you to fill values
+ * into. THIS IS A TEMPORARY POINTER and is only guaranteed to exist until the
+ * next time you do an operation on the hashtable. But you can safely fill it
+ * in.
+ *
+ * Returns nsnull if the entry cannot be created (usually a low memory
+ * constraint).
+ *
+ * void Remove(aKey)
+ * Remove the entry referenced by aKey. If the entry does not exist, nothing
+ * will happen.
+ *
+ *
+ * DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
+ *
+ * Declare the hash class but do not define the functions.
+ *
+ * CLASSNAME: the name of the class to declare.
+ * ENTRY_CLASS: the class of the entry struct.
+ * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
+ *
+ *
+ * DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
+ *
+ * Define the functions for the hash class.
+ *
+ * CLASSNAME: the name of the class to declare.
+ * ENTRY_CLASS: the class of the entry struct.
+ * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
+ *
+ *
+ * CAVEATS:
+ * - You may have only *one* wrapper class per entry class.
+ */
+
+#define DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+class DHASH_EXPORT CLASSNAME { \
+public: \
+ CLASSNAME(); \
+ ~CLASSNAME(); \
+ nsresult Init(PRUint32 aNumInitialEntries); \
+ ENTRY_CLASS* GetEntry(const KEY_TYPE aKey); \
+ ENTRY_CLASS* AddEntry(const KEY_TYPE aKey); \
+ void Remove(const KEY_TYPE aKey); \
+ PLDHashTable mHashTable; \
+};
+
+#define DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DHASH_CALLBACKS(ENTRY_CLASS) \
+CLASSNAME::CLASSNAME() { \
+ mHashTable.ops = nsnull; \
+} \
+CLASSNAME::~CLASSNAME() { \
+ if (mHashTable.ops) { \
+ PL_DHashTableFinish(&mHashTable); \
+ } \
+} \
+nsresult CLASSNAME::Init(PRUint32 aNumInitialEntries) { \
+ if (!mHashTable.ops) { \
+ nsresult rv; \
+ DHASH_INIT(mHashTable,ENTRY_CLASS,aNumInitialEntries,rv); \
+ return rv; \
+ } \
+ return NS_OK; \
+} \
+ENTRY_CLASS* CLASSNAME::GetEntry(const KEY_TYPE aKey) { \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*, \
+ PL_DHashTableOperate(&mHashTable, &aKey, \
+ PL_DHASH_LOOKUP)); \
+ return PL_DHASH_ENTRY_IS_BUSY(e) ? e : nsnull; \
+} \
+ENTRY_CLASS* CLASSNAME::AddEntry(const KEY_TYPE aKey) { \
+ return NS_STATIC_CAST(ENTRY_CLASS*, \
+ PL_DHashTableOperate(&mHashTable, &aKey, \
+ PL_DHASH_ADD)); \
+} \
+void CLASSNAME::Remove(const KEY_TYPE aKey) { \
+ PL_DHashTableOperate(&mHashTable, &aKey, PL_DHASH_REMOVE); \
+}
+
+/*
+ * STANDARD KEY ENTRY CLASSES
+ *
+ * We have declared some standard key classes for you to make life a little
+ * easier. These include string, int and void* keys. You can extend these
+ * and add value data members to make a working hash entry class with your
+ * values.
+ *
+ * PLDHashStringEntry: nsAString
+ * PLDHashCStringEntry: nsACString
+ * PLDHashInt32Entry: PRInt32
+ * PLDHashVoidEntry: void*
+ *
+ * As a short example, if you want to make a class that maps int to string,
+ * you could do:
+ *
+ * class MyIntStringEntry : public PLDHashInt32Entry
+ * {
+ * public:
+ * MyIntStringEntry(const void* aKey) : PLDHashInt32Entry(aKey) { }
+ * ~MyIntStringEntry() { };
+ * nsString mMyStr;
+ * };
+ *
+ * XXX It could be advisable (unless COW strings ever happens) to have a
+ * PLDHashDependentStringEntry
+ */
+
+//
+// String-key entry
+//
+class NS_COM PLDHashStringEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashStringEntry(const void* aKey) :
+ mKey(*NS_STATIC_CAST(const nsAString*, aKey)) { }
+ ~PLDHashStringEntry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const nsAString*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return HashString(*NS_STATIC_CAST(const nsAString*, key));
+ }
+ PRBool MatchEntry(const void* key) const {
+ return NS_STATIC_CAST(const nsAString*, key)->Equals(mKey);
+ }
+
+ const nsString mKey;
+};
+
+//
+// CString-key entry
+//
+class NS_COM PLDHashCStringEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashCStringEntry(const void* aKey) :
+ mKey(*NS_STATIC_CAST(const nsACString*, aKey)) { }
+ ~PLDHashCStringEntry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const nsACString*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return HashString(*NS_STATIC_CAST(const nsACString*, key));
+ }
+ PRBool MatchEntry(const void* key) const {
+ return NS_STATIC_CAST(const nsACString*, key)->Equals(mKey);
+ }
+
+ const nsCString mKey;
+};
+
+//
+// Int-key entry
+//
+class NS_COM PLDHashInt32Entry : public PLDHashEntryHdr
+{
+public:
+ PLDHashInt32Entry(const void* aKey) :
+ mKey(*(NS_STATIC_CAST(const PRInt32*, aKey))) { }
+ ~PLDHashInt32Entry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const PRInt32*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return *NS_STATIC_CAST(const PRInt32*, key);
+ }
+ PRBool MatchEntry(const void* key) const {
+ return *(NS_STATIC_CAST(const PRInt32*, key)) == mKey;
+ }
+
+ const PRInt32 mKey;
+};
+
+
+//
+// Void-key entry
+//
+class NS_COM PLDHashVoidEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashVoidEntry(const void* aKey) :
+ mKey(*(const void**)aKey) { }
+ ~PLDHashVoidEntry() { }
+
+ const void* GetKey() const {
+ return (const void**)&mKey;
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return PLDHashNumber(NS_PTR_TO_INT32(*(const void**)key)) >> 2;
+ }
+ PRBool MatchEntry(const void* key) const {
+ return *(const void**)key == mKey;
+ }
+
+ const void* mKey;
+};
+
+
+#define DHASH_EXPORT
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp
new file mode 100644
index 00000000..c00d118c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ An empty enumerator.
+
+ */
+
+#include "nsEmptyEnumerator.h"
+
+////////////////////////////////////////////////////////////////////////
+
+MOZ_DECL_CTOR_COUNTER(EmptyEnumeratorImpl)
+
+EmptyEnumeratorImpl::EmptyEnumeratorImpl(void)
+{
+ MOZ_COUNT_CTOR(EmptyEnumeratorImpl);
+}
+
+EmptyEnumeratorImpl::~EmptyEnumeratorImpl(void)
+{
+ MOZ_COUNT_DTOR(EmptyEnumeratorImpl);
+}
+
+// nsISupports interface
+NS_IMETHODIMP_(nsrefcnt) EmptyEnumeratorImpl::AddRef(void)
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt) EmptyEnumeratorImpl::Release(void)
+{
+ return 1;
+}
+
+NS_IMPL_QUERY_INTERFACE1(EmptyEnumeratorImpl, nsISimpleEnumerator)
+
+
+// nsISimpleEnumerator interface
+NS_IMETHODIMP EmptyEnumeratorImpl::HasMoreElements(PRBool* aResult)
+{
+ *aResult = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
+{
+ return NS_ERROR_UNEXPECTED;
+}
+
+static EmptyEnumeratorImpl* gEmptyEnumerator = nsnull;
+
+extern "C" NS_COM nsresult
+NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
+{
+ nsresult rv = NS_OK;
+ if (!gEmptyEnumerator) {
+ gEmptyEnumerator = new EmptyEnumeratorImpl();
+ if (!gEmptyEnumerator)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aResult = gEmptyEnumerator;
+ return rv;
+}
+
+/* static */ void
+EmptyEnumeratorImpl::Shutdown()
+{
+ delete gEmptyEnumerator;
+ gEmptyEnumerator = nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h
new file mode 100644
index 00000000..4b2feabe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ An empty enumerator.
+
+ */
+
+#include "nsIEnumerator.h"
+
+////////////////////////////////////////////////////////////////////////
+
+class EmptyEnumeratorImpl : public nsISimpleEnumerator
+{
+public:
+ EmptyEnumeratorImpl(void);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt
+
+ // nsISimpleEnumerator
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ static void Shutdown();
+
+private:
+ ~EmptyEnumeratorImpl(void);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp
new file mode 100644
index 00000000..e91f68e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsEnumeratorUtils.h"
+
+
+nsArrayEnumerator::nsArrayEnumerator(nsISupportsArray* aValueArray)
+ : mValueArray(aValueArray),
+ mIndex(0)
+{
+ NS_IF_ADDREF(mValueArray);
+}
+
+nsArrayEnumerator::~nsArrayEnumerator(void)
+{
+ NS_IF_RELEASE(mValueArray);
+}
+
+NS_IMPL_ISUPPORTS1(nsArrayEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ *aResult = (mIndex < (PRInt32) cnt);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mIndex >= (PRInt32) cnt)
+ return NS_ERROR_UNEXPECTED;
+
+ *aResult = mValueArray->ElementAt(mIndex++);
+ return NS_OK;
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsISupportsArray* array)
+{
+ nsArrayEnumerator* enumer = new nsArrayEnumerator(array);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
+ : mValue(aValue)
+{
+ NS_IF_ADDREF(mValue);
+ mConsumed = (mValue ? PR_FALSE : PR_TRUE);
+}
+
+nsSingletonEnumerator::~nsSingletonEnumerator()
+{
+ NS_IF_RELEASE(mValue);
+}
+
+NS_IMPL_ISUPPORTS1(nsSingletonEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsSingletonEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ *aResult = !mConsumed;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsSingletonEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mConsumed)
+ return NS_ERROR_UNEXPECTED;
+
+ mConsumed = PR_TRUE;
+
+ *aResult = mValue;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+extern "C" NS_COM nsresult
+NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
+ nsISupports* singleton)
+{
+ nsSingletonEnumerator* enumer = new nsSingletonEnumerator(singleton);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator)
+ : mFirstEnumerator(firstEnumerator),
+ mSecondEnumerator(secondEnumerator),
+ mConsumed(PR_FALSE), mAtSecond(PR_FALSE)
+{
+}
+
+nsUnionEnumerator::~nsUnionEnumerator()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsUnionEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsUnionEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+
+ if (mConsumed) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ if (! mAtSecond) {
+ rv = mFirstEnumerator->HasMoreElements(aResult);
+ if (NS_FAILED(rv)) return rv;
+
+ if (*aResult)
+ return NS_OK;
+
+ mAtSecond = PR_TRUE;
+ }
+
+ rv = mSecondEnumerator->HasMoreElements(aResult);
+ if (NS_FAILED(rv)) return rv;
+
+ if (*aResult)
+ return NS_OK;
+
+ *aResult = PR_FALSE;
+ mConsumed = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsUnionEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mConsumed)
+ return NS_ERROR_UNEXPECTED;
+
+ if (! mAtSecond)
+ return mFirstEnumerator->GetNext(aResult);
+
+ return mSecondEnumerator->GetNext(aResult);
+}
+
+extern "C" NS_COM nsresult
+NS_NewUnionEnumerator(nsISimpleEnumerator* *result,
+ nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator)
+{
+ *result = nsnull;
+ if (! firstEnumerator) {
+ *result = secondEnumerator;
+ } else if (! secondEnumerator) {
+ *result = firstEnumerator;
+ } else {
+ nsUnionEnumerator* enumer = new nsUnionEnumerator(firstEnumerator, secondEnumerator);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ }
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h
new file mode 100644
index 00000000..2d8182b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsEnumeratorUtils_h__
+#define nsEnumeratorUtils_h__
+
+#include "nsIEnumerator.h"
+#include "nsISupportsArray.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewSingletonEnumerator VBoxNsxpNS_NewSingletonEnumerator
+#define NS_NewUnionEnumerator VBoxNsxpNS_NewUnionEnumerator
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class NS_COM nsArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ // nsArrayEnumerator methods
+ nsArrayEnumerator(nsISupportsArray* aValueArray);
+
+private:
+ ~nsArrayEnumerator(void);
+
+protected:
+ nsISupportsArray* mValueArray;
+ PRInt32 mIndex;
+};
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsISupportsArray* array);
+
+////////////////////////////////////////////////////////////////////////////////
+
+class NS_COM nsSingletonEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator methods
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ nsSingletonEnumerator(nsISupports* aValue);
+
+private:
+ ~nsSingletonEnumerator();
+
+protected:
+ nsISupports* mValue;
+ PRBool mConsumed;
+};
+
+extern "C" NS_COM nsresult
+NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
+ nsISupports* singleton);
+
+////////////////////////////////////////////////////////////////////////
+
+class NS_COM nsUnionEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator methods
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator);
+
+private:
+ ~nsUnionEnumerator();
+
+protected:
+ nsCOMPtr<nsISimpleEnumerator> mFirstEnumerator, mSecondEnumerator;
+ PRBool mConsumed;
+ PRBool mAtSecond;
+};
+
+extern "C" NS_COM nsresult
+NS_NewUnionEnumerator(nsISimpleEnumerator* *result,
+ nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator);
+
+////////////////////////////////////////////////////////////////////////
+
+#endif /* nsEnumeratorUtils_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp
new file mode 100644
index 00000000..1b6232f9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Waterson <waterson@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ Implementation for nsFixedSizeAllocator
+
+*/
+
+#include "nsCRT.h"
+#include "nsFixedSizeAllocator.h"
+
+nsFixedSizeAllocator::Bucket *
+nsFixedSizeAllocator::AddBucket(size_t aSize)
+{
+ void* p;
+ PL_ARENA_ALLOCATE(p, &mPool, sizeof(Bucket));
+ if (! p)
+ return nsnull;
+
+ Bucket* bucket = NS_STATIC_CAST(Bucket*, p);
+ bucket->mSize = aSize;
+ bucket->mFirst = nsnull;
+ bucket->mNext = mBuckets;
+
+ mBuckets = bucket;
+ return bucket;
+}
+
+nsresult
+nsFixedSizeAllocator::Init(const char* aName,
+ const size_t* aBucketSizes,
+ PRInt32 aNumBuckets,
+ PRInt32 aInitialSize,
+ PRInt32 aAlign)
+{
+ NS_PRECONDITION(aNumBuckets > 0, "no buckets");
+ if (aNumBuckets <= 0)
+ return NS_ERROR_INVALID_ARG;
+
+ // Blow away the old pool if we're being re-initialized.
+ if (mBuckets)
+ PL_FinishArenaPool(&mPool);
+
+ PRInt32 bucketspace = aNumBuckets * sizeof(Bucket);
+ PL_InitArenaPool(&mPool, aName, bucketspace + aInitialSize, aAlign);
+
+ mBuckets = nsnull;
+ for (PRInt32 i = 0; i < aNumBuckets; ++i)
+ AddBucket(aBucketSizes[i]);
+
+ return NS_OK;
+}
+
+nsFixedSizeAllocator::Bucket *
+nsFixedSizeAllocator::FindBucket(size_t aSize)
+{
+ Bucket** link = &mBuckets;
+ Bucket* bucket;
+
+ while ((bucket = *link) != nsnull) {
+ if (aSize == bucket->mSize) {
+ // Promote to the head of the list, under the assumption
+ // that we'll allocate same-sized object contemporaneously.
+ *link = bucket->mNext;
+ bucket->mNext = mBuckets;
+ mBuckets = bucket;
+ return bucket;
+ }
+
+ link = &bucket->mNext;
+ }
+ return nsnull;
+}
+
+void*
+nsFixedSizeAllocator::Alloc(size_t aSize)
+{
+ Bucket* bucket = FindBucket(aSize);
+ if (! bucket) {
+ // Oops, we don't carry that size. Let's fix that.
+ bucket = AddBucket(aSize);
+ if (! bucket)
+ return nsnull;
+ }
+
+ void* next;
+ if (bucket->mFirst) {
+ next = bucket->mFirst;
+ bucket->mFirst = bucket->mFirst->mNext;
+ }
+ else {
+ PL_ARENA_ALLOCATE(next, &mPool, aSize);
+ if (!next)
+ return nsnull;
+ }
+
+#ifdef DEBUG
+ memset(next, 0xc8, aSize);
+#endif
+
+ return next;
+}
+
+void
+nsFixedSizeAllocator::Free(void* aPtr, size_t aSize)
+{
+ FreeEntry* entry = NS_REINTERPRET_CAST(FreeEntry*, aPtr);
+ Bucket* bucket = FindBucket(aSize);
+
+#ifdef DEBUG
+ NS_ASSERTION(bucket && bucket->mSize == aSize, "ack! corruption! bucket->mSize != aSize!");
+ memset(aPtr, 0xd8, bucket->mSize);
+#endif
+
+ entry->mNext = bucket->mFirst;
+ bucket->mFirst = entry;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h
new file mode 100644
index 00000000..16708cdc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Waterson <waterson@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ A simple fixed-size allocator that allocates its memory from an
+ arena.
+
+ Although the allocator can handle blocks of any size, its
+ preformance will degrade rapidly if used to allocate blocks of
+ arbitrary size. Ideally, it should be used to allocate and recycle a
+ large number of fixed-size blocks.
+
+ Here is a typical usage pattern:
+
+ #include NEW_H // You'll need this!
+ #include "nsFixedSizeAllocator.h"
+
+ // Say this is the object you want to allocate a ton of
+ class Foo {
+ public:
+ // Implement placement new & delete operators that will
+ // use the fixed size allocator.
+ static Foo *
+ Create(nsFixedSizeAllocator &aAllocator)
+ {
+ void *place = aAllocator.Alloc(sizeof(Foo));
+ return place ? ::new (place) Foo() : nsnull;
+ }
+
+ static void
+ Destroy(nsFixedSizeAllocator &aAllocator, Foo *aFoo)
+ {
+ aFoo->~Foo();
+ aAllocator.Free(aFoo, sizeof(Foo));
+ }
+
+ // ctor & dtor
+ Foo() {}
+ ~Foo() {}
+ };
+
+
+ int main(int argc, char* argv[])
+ {
+ // Somewhere in your code, you'll need to create an
+ // nsFixedSizeAllocator object and initialize it:
+ nsFixedSizeAllocator pool;
+
+ // The fixed size allocator will support multiple fixed sizes.
+ // This array lists an initial set of sizes that the allocator
+ // should be prepared to support. In our case, there's just one,
+ // which is Foo.
+ static const size_t kBucketSizes[]
+ = { sizeof(Foo) }
+
+ // This is the number of different "buckets" you'll need for
+ // fixed size objects. In our example, this will be "1".
+ static const PRInt32 kNumBuckets
+ = sizeof(kBucketSizes) / sizeof(size_t);
+
+ // This is the intial size of the allocator, in bytes. We'll
+ // assume that we want to start with space for 1024 Foo objects.
+ static const PRInt32 kInitialPoolSize =
+ NS_SIZE_IN_HEAP(sizeof(Foo)) * 1024;
+
+ // Initialize (or re-initialize) the pool
+ pool.Init("TheFooPool", kBucketSizes, kNumBuckets, kInitialPoolSize);
+
+ // Now we can use the pool.
+
+ // Create a new Foo object using the pool:
+ Foo* foo = Foo::Create(pool);
+ if (! foo) {
+ // uh oh, out of memory!
+ }
+
+ // Delete the object. The memory used by `foo' is recycled in
+ // the pool, and placed in a freelist
+ Foo::Destroy(foo);
+
+ // Create another foo: this one will be allocated from the
+ // free-list
+ foo = Foo::Create(pool);
+
+ // When pool is destroyed, all of its memory is automatically
+ // freed. N.B. it will *not* call your objects' destructors! In
+ // this case, foo's ~Foo() method would never be called.
+ }
+
+*/
+
+#ifndef nsFixedSizeAllocator_h__
+#define nsFixedSizeAllocator_h__
+
+#include "nscore.h"
+#include "nsError.h"
+#include "plarena.h"
+
+#define NS_SIZE_IN_HEAP(_size) (_size)
+
+class NS_COM nsFixedSizeAllocator
+{
+protected:
+ PLArenaPool mPool;
+
+ struct Bucket;
+ struct FreeEntry;
+
+ friend struct Bucket;
+ friend struct FreeEntry;
+
+ struct FreeEntry {
+ FreeEntry* mNext;
+ };
+
+ struct Bucket {
+ size_t mSize;
+ FreeEntry* mFirst;
+ Bucket* mNext;
+ };
+
+ Bucket* mBuckets;
+
+ Bucket *
+ AddBucket(size_t aSize);
+
+ Bucket *
+ FindBucket(size_t aSize);
+
+public:
+ nsFixedSizeAllocator() : mBuckets(nsnull) {}
+
+ ~nsFixedSizeAllocator() {
+ if (mBuckets)
+ PL_FinishArenaPool(&mPool);
+ }
+
+ /**
+ * Initialize the fixed size allocator. 'aName' is used to tag
+ * the underlying PLArena object for debugging and measurement
+ * purposes. 'aNumBuckets' specifies the number of elements in
+ * 'aBucketSizes', which is an array of integral block sizes
+ * that this allocator should be prepared to handle.
+ */
+ nsresult
+ Init(const char* aName,
+ const size_t* aBucketSizes,
+ PRInt32 aNumBuckets,
+ PRInt32 aInitialSize,
+ PRInt32 aAlign = 0);
+
+ /**
+ * Allocate a block of memory 'aSize' bytes big.
+ */
+ void* Alloc(size_t aSize);
+
+ /**
+ * Free a pointer allocated using a fixed-size allocator
+ */
+ void Free(void* aPtr, size_t aSize);
+};
+
+
+
+#endif // nsFixedSizeAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h b/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h
new file mode 100644
index 00000000..8a6d272e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTHashKeys_h__
+#define nsTHashKeys_h__
+
+#include "nsAString.h"
+#include "nsString.h"
+#include "nsID.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+#include "pldhash.h"
+#include NEW_H
+
+/** @file nsHashKeys.h
+ * standard HashKey classes for nsBaseHashtable and relatives. Each of these
+ * classes follows the nsTHashtable::EntryType specification
+ *
+ * Lightweight keytypes provided here:
+ * nsStringHashKey
+ * nsCStringHashKey
+ * nsUint32HashKey
+ * nsISupportsHashKey
+ * nsIDHashKey
+ * nsDepCharHashKey
+ */
+
+/**
+ * hashkey wrapper using nsAString KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsStringHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsAString& KeyType;
+ typedef const nsAString* KeyTypePointer;
+
+ nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { }
+ nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+ ~nsStringHashKey() { }
+
+ KeyType GetKey() const { return mStr; }
+ KeyTypePointer GetKeyPointer() const { return &mStr; }
+ PRBool KeyEquals(const KeyTypePointer aKey) const
+ {
+ return mStr.Equals(*aKey);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(const KeyTypePointer aKey)
+ {
+ return HashString(*aKey);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsString mStr;
+};
+
+/**
+ * hashkey wrapper using nsACString KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsCStringHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsACString& KeyType;
+ typedef const nsACString* KeyTypePointer;
+
+ nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { }
+ nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+ ~nsCStringHashKey() { }
+
+ KeyType GetKey() const { return mStr; }
+ KeyTypePointer GetKeyPointer() const { return &mStr; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return HashString(*aKey);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsCString mStr;
+};
+
+/**
+ * hashkey wrapper using PRUint32 KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsUint32HashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const PRUint32& KeyType;
+ typedef const PRUint32* KeyTypePointer;
+
+ nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
+ nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { }
+ ~nsUint32HashKey() { }
+
+ KeyType GetKey() const { return mValue; }
+ KeyTypePointer GetKeyPointer() const { return &mValue; }
+ PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const PRUint32 mValue;
+};
+
+/**
+ * hashkey wrapper using nsISupports* KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsISupportsHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef nsISupports* KeyType;
+ typedef const nsISupports* KeyTypePointer;
+
+ nsISupportsHashKey(const nsISupports* key) :
+ mSupports(NS_CONST_CAST(nsISupports*,key)) { }
+ nsISupportsHashKey(const nsISupportsHashKey& toCopy) :
+ mSupports(toCopy.mSupports) { }
+ ~nsISupportsHashKey() { }
+
+ KeyType GetKey() const { return mSupports; }
+ KeyTypePointer GetKeyPointer() const { return mSupports; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return NS_PTR_TO_INT32(aKey) >>2;
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ nsCOMPtr<nsISupports> mSupports;
+};
+
+/**
+ * hashkey wrapper using void* KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsVoidPtrHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const void* KeyType;
+ typedef const void* KeyTypePointer;
+
+ nsVoidPtrHashKey(const void* key) :
+ mKey(key) { }
+ nsVoidPtrHashKey(const nsVoidPtrHashKey& toCopy) :
+ mKey(toCopy.mKey) { }
+ ~nsVoidPtrHashKey() { }
+
+ KeyType GetKey() const { return mKey; }
+ KeyTypePointer GetKeyPointer() const { return mKey; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return NS_PTR_TO_INT32(aKey) >>2;
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const void* mKey;
+};
+
+/**
+ * hashkey wrapper using nsID KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsIDHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsID& KeyType;
+ typedef const nsID* KeyTypePointer;
+
+ nsIDHashKey(const nsID* id) : mID(*id) { }
+ nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
+ ~nsIDHashKey() { }
+
+ KeyType GetKey() const { return mID; }
+ KeyTypePointer GetKeyPointer() const { return &mID; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey);
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsID mID;
+};
+
+/**
+ * hashkey wrapper for "dependent" const char*; this class does not "own"
+ * its string pointer.
+ *
+ * This class must only be used if the strings have a lifetime longer than
+ * the hashtable they occupy. This normally occurs only for static
+ * strings or strings that have been arena-allocated.
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsDepCharHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ nsDepCharHashKey(const char* aKey) { mKey = aKey; }
+ nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
+ ~nsDepCharHashKey() { }
+
+ const char* GetKey() const { return mKey; }
+ const char* GetKeyPointer() const { return mKey; }
+ PRBool KeyEquals(const char* aKey) const
+ {
+ return !strcmp(mKey, aKey);
+ }
+
+ static const char* KeyToPointer(const char* aKey) { return aKey; }
+ static PLDHashNumber HashKey(const char* aKey) { return nsCRT::HashCode(aKey); }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const char* mKey;
+};
+
+/**
+ * hashkey wrapper for const char*; at construction, this class duplicates
+ * a string pointed to by the pointer so that it doesn't matter whether or not
+ * the string lives longer than the hash table.
+ */
+class NS_COM nsCharPtrHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) { }
+ nsCharPtrHashKey(const nsCharPtrHashKey& toCopy) : mKey(strdup(toCopy.mKey)) { }
+ ~nsCharPtrHashKey() { if (mKey) free(NS_CONST_CAST(char *, mKey)); }
+
+ const char* GetKey() const { return mKey; }
+ const char* GetKeyPointer() const { return mKey; }
+ PRBool KeyEquals(KeyTypePointer aKey) const
+ {
+ return !strcmp(mKey, aKey);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) { return nsCRT::HashCode(aKey); }
+
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const char* mKey;
+};
+
+#endif // nsTHashKeys_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp
new file mode 100644
index 00000000..3f11ba55
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nscore.h"
+#include NEW_H
+
+#include "nsHashSets.h"
+
+DHASH_SET(nsStringHashSet, PLDHashStringEntry, nsAString&)
+DHASH_SET(nsCStringHashSet,PLDHashCStringEntry,nsACString&)
+DHASH_SET(nsInt32HashSet, PLDHashInt32Entry, PRInt32)
+DHASH_SET(nsVoidHashSet, PLDHashVoidEntry, void*)
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h
new file mode 100644
index 00000000..627a6a06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsHashSets_h__
+#define __nsHashSets_h__
+
+#include "nsDoubleHashtable.h"
+
+/*
+ * HASH SETS
+ *
+ * These hash classes describe hashtables that contain keys without values.
+ * This is useful when you want to store things and then just test for their
+ * existence later. We have defined standard ones for string, int and void.
+ *
+ * nsStringHashSet: nsAString&
+ * nsCStringHashSet: nsACString&
+ * nsInt32HashSet: PRInt32
+ * nsVoidHashSet: void*
+ *
+ * USAGE:
+ * Put(): put a thing of the given type into the set
+ * Contains(): whether it contains a thing of the given type
+ * To use, you just do: (for example)
+ *
+ * #include "nsDoubleHashtable.h"
+ * nsInt32HashSet mySet;
+ * mySet.Init(1);
+ * mySet.Put(5);
+ * if (mySet.Contains(5)) {
+ * printf("yay\n");
+ * }
+ *
+ * There is a nice convenient macro for declaring empty map classes:
+ * DECL_DHASH_SET(CLASSNAME, ENTRY_CLASS, KEY_TYPE)
+ * - CLASSNAME: the name of the class
+ * - ENTRY_CLASS: the name of the entry class with the key in it
+ * - KEY_TYPE: the type of key for Put() and Contains()
+ *
+ * DHASH_SET(CLASSNAME, ENTRY_CLASS, KEY_TYPE) is the companion macro
+ * you must put in the .cpp (implementation) code.
+ */
+
+#define DECL_DHASH_SET(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DECL_DHASH_WRAPPER(CLASSNAME##Super,ENTRY_CLASS,KEY_TYPE) \
+class DHASH_EXPORT CLASSNAME : public CLASSNAME##Super { \
+public: \
+ CLASSNAME() : CLASSNAME##Super() { } \
+ ~CLASSNAME() { } \
+ nsresult Put(const KEY_TYPE aKey) { \
+ return AddEntry(aKey) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; \
+ } \
+ PRBool Contains(const KEY_TYPE aKey) { \
+ return GetEntry(aKey) ? PR_TRUE : PR_FALSE; \
+ } \
+};
+
+#define DHASH_SET(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DHASH_WRAPPER(CLASSNAME##Super,ENTRY_CLASS,KEY_TYPE)
+
+#undef DHASH_EXPORT
+#define DHASH_EXPORT NS_COM
+
+DECL_DHASH_SET(nsStringHashSet, PLDHashStringEntry, nsAString&)
+DECL_DHASH_SET(nsCStringHashSet,PLDHashCStringEntry,nsACString&)
+DECL_DHASH_SET(nsInt32HashSet, PLDHashInt32Entry, PRInt32)
+DECL_DHASH_SET(nsVoidHashSet, PLDHashVoidEntry, void*)
+
+#undef DHASH_EXPORT
+#define DHASH_EXPORT
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp
new file mode 100644
index 00000000..ce74fb28
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp
@@ -0,0 +1,896 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * 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
+ */
+
+#include <string.h>
+#include "prmem.h"
+#include "prlog.h"
+#include "nsHashtable.h"
+#include "nsReadableUtils.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsCRT.h"
+
+struct HTEntry : PLDHashEntryHdr
+{
+ nsHashKey* key;
+ void* value;
+};
+
+//
+// Key operations
+//
+
+PR_STATIC_CALLBACK(PRBool)
+matchKeyEntry(PLDHashTable*, const PLDHashEntryHdr* entry,
+ const void* key)
+{
+ const HTEntry* hashEntry =
+ NS_STATIC_CAST(const HTEntry*, entry);
+
+ if (hashEntry->key == key)
+ return PR_TRUE;
+
+ const nsHashKey* otherKey = NS_REINTERPRET_CAST(const nsHashKey*, key);
+ return otherKey->Equals(hashEntry->key);
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+hashKey(PLDHashTable* table, const void* key)
+{
+ const nsHashKey* hashKey = NS_STATIC_CAST(const nsHashKey*, key);
+
+ return hashKey->HashCode();
+}
+
+PR_STATIC_CALLBACK(void)
+clearHashEntry(PLDHashTable* table, PLDHashEntryHdr* entry)
+{
+ HTEntry* hashEntry = NS_STATIC_CAST(HTEntry*, entry);
+
+ // leave it up to the nsHashKey destructor to free the "value"
+ delete hashEntry->key;
+ hashEntry->key = nsnull;
+ hashEntry->value = nsnull; // probably not necessary, but for
+ // sanity's sake
+}
+
+
+static const PLDHashTableOps hashtableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ hashKey,
+ matchKeyEntry,
+ PL_DHashMoveEntryStub,
+ clearHashEntry,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+
+//
+// Enumerator callback
+//
+
+struct _HashEnumerateArgs {
+ nsHashtableEnumFunc fn;
+ void* arg;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerate(PLDHashTable* table, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
+{
+ _HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ switch (thunk->fn(entry->key, entry->value, thunk->arg)) {
+ case kHashEnumerateNext:
+ return PL_DHASH_NEXT;
+ case kHashEnumerateRemove:
+ return PL_DHASH_REMOVE;
+ }
+ return PL_DHASH_STOP;
+}
+
+//
+// HashKey
+//
+
+nsHashKey::~nsHashKey(void)
+{
+ MOZ_COUNT_DTOR(nsHashKey);
+}
+
+nsresult
+nsHashKey::Write(nsIObjectOutputStream* aStream) const
+{
+ NS_NOTREACHED("oops");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+MOZ_DECL_CTOR_COUNTER(nsHashtable)
+
+nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe)
+ : mLock(NULL), mEnumerating(PR_FALSE)
+{
+ MOZ_COUNT_CTOR(nsHashtable);
+
+ PRBool result = PL_DHashTableInit(&mHashtable, &hashtableOps, nsnull,
+ sizeof(HTEntry), aInitSize);
+
+ NS_ASSERTION(result, "Hashtable failed to initialize");
+
+ // make sure we detect this later
+ if (!result)
+ mHashtable.ops = nsnull;
+
+ if (threadSafe) {
+ mLock = PR_NewLock();
+ if (mLock == NULL) {
+ // Cannot create a lock. If running on a multiprocessing system
+ // we are sure to die.
+ PR_ASSERT(mLock != NULL);
+ }
+ }
+}
+
+
+nsHashtable::~nsHashtable() {
+ MOZ_COUNT_DTOR(nsHashtable);
+ if (mHashtable.ops)
+ PL_DHashTableFinish(&mHashtable);
+ if (mLock) PR_DestroyLock(mLock);
+}
+
+PRBool nsHashtable::Exists(nsHashKey *aKey)
+{
+ if (mLock) PR_Lock(mLock);
+
+ if (!mHashtable.ops)
+ return PR_FALSE;
+
+ PLDHashEntryHdr *entry =
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP);
+
+ PRBool exists = PL_DHASH_ENTRY_IS_BUSY(entry);
+
+ if (mLock) PR_Unlock(mLock);
+
+ return exists;
+}
+
+void *nsHashtable::Put(nsHashKey *aKey, void *aData)
+{
+ void *res = NULL;
+
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ // shouldn't be adding an item during enumeration
+ PR_ASSERT(!mEnumerating);
+
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_ADD));
+
+ if (entry) { // don't return early, or you'll be locked!
+ if (entry->key) {
+ // existing entry, need to boot the old value
+ res = entry->value;
+ entry->value = aData;
+ } else {
+ // new entry (leave res == null)
+ entry->key = aKey->Clone();
+ entry->value = aData;
+ }
+ }
+
+ if (mLock) PR_Unlock(mLock);
+
+ return res;
+}
+
+void *nsHashtable::Get(nsHashKey *aKey)
+{
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
+ void *ret = PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->value : nsnull;
+
+ if (mLock) PR_Unlock(mLock);
+
+ return ret;
+}
+
+void *nsHashtable::Remove(nsHashKey *aKey)
+{
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ // shouldn't be adding an item during enumeration
+ PR_ASSERT(!mEnumerating);
+
+
+ // need to see if the entry is actually there, in order to get the
+ // old value for the result
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
+ void *res;
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ // value wasn't in the table anyway
+ res = nsnull;
+ } else {
+ res = entry->value;
+ PL_DHashTableRawRemove(&mHashtable, entry);
+ }
+
+ if (mLock) PR_Unlock(mLock);
+
+ return res;
+}
+
+// XXX This method was called _hashEnumerateCopy, but it didn't copy the element!
+// I don't know how this was supposed to work since the elements are neither copied
+// nor refcounted.
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerateShare(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 i, void *arg)
+{
+ nsHashtable *newHashtable = (nsHashtable *)arg;
+ HTEntry * entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ newHashtable->Put(entry->key, entry->value);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable * nsHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = (mLock != nsnull);
+ nsHashtable *newHashTable = new nsHashtable(mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerateShare, newHashTable);
+ return newHashTable;
+}
+
+void nsHashtable::Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure)
+{
+ if (!mHashtable.ops) return;
+
+ PRBool wasEnumerating = mEnumerating;
+ mEnumerating = PR_TRUE;
+ _HashEnumerateArgs thunk;
+ thunk.fn = aEnumFunc;
+ thunk.arg = aClosure;
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerate, &thunk);
+ mEnumerating = wasEnumerating;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerateRemove(PLDHashTable*, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
+{
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+ _HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
+ if (thunk) {
+ return thunk->fn(entry->key, entry->value, thunk->arg)
+ ? PL_DHASH_REMOVE
+ : PL_DHASH_STOP;
+ }
+ return PL_DHASH_REMOVE;
+}
+
+void nsHashtable::Reset() {
+ Reset(NULL);
+}
+
+void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* aClosure)
+{
+ if (!mHashtable.ops) return;
+
+ _HashEnumerateArgs thunk, *thunkp;
+ if (!destroyFunc) {
+ thunkp = nsnull;
+ } else {
+ thunkp = &thunk;
+ thunk.fn = destroyFunc;
+ thunk.arg = aClosure;
+ }
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerateRemove, thunkp);
+}
+
+// nsISerializable helpers
+
+nsHashtable::nsHashtable(nsIObjectInputStream* aStream,
+ nsHashtableReadEntryFunc aReadEntryFunc,
+ nsHashtableFreeEntryFunc aFreeEntryFunc,
+ nsresult *aRetVal)
+ : mLock(nsnull),
+ mEnumerating(PR_FALSE)
+{
+ MOZ_COUNT_CTOR(nsHashtable);
+
+ PRBool threadSafe;
+ nsresult rv = aStream->ReadBoolean(&threadSafe);
+ if (NS_SUCCEEDED(rv)) {
+ if (threadSafe) {
+ mLock = PR_NewLock();
+ if (!mLock)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ PRUint32 count;
+ rv = aStream->Read32(&count);
+
+ if (NS_SUCCEEDED(rv)) {
+ PRBool status =
+ PL_DHashTableInit(&mHashtable, &hashtableOps,
+ nsnull, sizeof(HTEntry), count);
+ if (!status) {
+ mHashtable.ops = nsnull;
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ for (PRUint32 i = 0; i < count; i++) {
+ nsHashKey* key;
+ void *data;
+
+ rv = aReadEntryFunc(aStream, &key, &data);
+ if (NS_SUCCEEDED(rv)) {
+ if (!Put(key, data)) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ aFreeEntryFunc(aStream, key, data);
+ } else {
+ // XXXbe must we clone key? can't we hand off
+ aFreeEntryFunc(aStream, key, nsnull);
+ }
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ *aRetVal = rv;
+}
+
+struct WriteEntryArgs {
+ nsIObjectOutputStream* mStream;
+ nsHashtableWriteDataFunc mWriteDataFunc;
+ nsresult mRetVal;
+};
+
+PR_STATIC_CALLBACK(PRBool)
+WriteEntry(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ WriteEntryArgs* args = (WriteEntryArgs*) aClosure;
+ nsIObjectOutputStream* stream = args->mStream;
+
+ nsresult rv = aKey->Write(stream);
+ if (NS_SUCCEEDED(rv))
+ rv = args->mWriteDataFunc(stream, aData);
+
+ args->mRetVal = rv;
+ return PR_TRUE;
+}
+
+nsresult
+nsHashtable::Write(nsIObjectOutputStream* aStream,
+ nsHashtableWriteDataFunc aWriteDataFunc) const
+{
+ if (!mHashtable.ops)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PRBool threadSafe = (mLock != nsnull);
+ nsresult rv = aStream->WriteBoolean(threadSafe);
+ if (NS_FAILED(rv)) return rv;
+
+ // Write the entry count first, so we know how many key/value pairs to read.
+ PRUint32 count = mHashtable.entryCount;
+ rv = aStream->Write32(count);
+ if (NS_FAILED(rv)) return rv;
+
+ // Write all key/value pairs in the table.
+ WriteEntryArgs args = {aStream, aWriteDataFunc};
+ NS_CONST_CAST(nsHashtable*, this)->Enumerate(WriteEntry, (void*) &args);
+ return args.mRetVal;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsISupportsKey::nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mKey(nsnull)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->ReadObject(PR_TRUE, &mKey);
+ *aResult = rv;
+}
+
+nsresult
+nsISupportsKey::Write(nsIObjectOutputStream* aStream) const
+{
+ PRBool nonnull = (mKey != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteObject(mKey, PR_TRUE);
+ return rv;
+}
+
+nsIDKey::nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult)
+{
+ *aResult = aStream->ReadID(&mID);
+}
+
+nsresult nsIDKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteID(mID);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Copy Constructor
+// We need to free mStr if the object is passed with mOwnership as OWN. As the
+// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
+
+nsCStringKey::nsCStringKey(const nsCStringKey& aKey)
+ : mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
+{
+ if (mOwnership != NEVER_OWN) {
+ PRUint32 len = mStrLen * sizeof(char);
+ char* str = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(len + sizeof(char)));
+ if (!str) {
+ // Pray we don't dangle!
+ mOwnership = NEVER_OWN;
+ } else {
+ // Use memcpy in case there are embedded NULs.
+ memcpy(str, mStr, len);
+ str[mStrLen] = '\0';
+ mStr = str;
+ mOwnership = OWN;
+ }
+ }
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const nsAFlatCString& str)
+ : mStr(NS_CONST_CAST(char*, str.get())),
+ mStrLen(str.Length()),
+ mOwnership(OWN_CLONE)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const nsACString& str)
+ : mStr(ToNewCString(str)),
+ mStrLen(str.Length()),
+ mOwnership(OWN)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const char* str, PRInt32 strLen, Ownership own)
+ : mStr((char*)str), mStrLen(strLen), mOwnership(own)
+{
+ NS_ASSERTION(mStr, "null string key");
+ if (mStrLen == PRUint32(-1))
+ mStrLen = strlen(str);
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::~nsCStringKey(void)
+{
+ if (mOwnership == OWN)
+ nsMemory::Free(mStr);
+ MOZ_COUNT_DTOR(nsCStringKey);
+}
+
+PRUint32
+nsCStringKey::HashCode(void) const
+{
+ return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+}
+
+PRBool
+nsCStringKey::Equals(const nsHashKey* aKey) const
+{
+ NS_ASSERTION(aKey->GetKeyType() == CStringKey, "mismatched key types");
+ nsCStringKey* other = (nsCStringKey*)aKey;
+ NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
+ NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
+ if (mStrLen != other->mStrLen)
+ return PR_FALSE;
+ return memcmp(mStr, other->mStr, mStrLen * sizeof(char)) == 0;
+}
+
+nsHashKey*
+nsCStringKey::Clone() const
+{
+ if (mOwnership == NEVER_OWN)
+ return new nsCStringKey(mStr, mStrLen, NEVER_OWN);
+
+ // Since this might hold binary data OR a string, we ensure that the
+ // clone string is zero terminated, but don't assume that the source
+ // string was so terminated.
+
+ PRUint32 len = mStrLen * sizeof(char);
+ char* str = (char*)nsMemory::Alloc(len + sizeof(char));
+ if (str == NULL)
+ return NULL;
+ memcpy(str, mStr, len);
+ str[len] = 0;
+ return new nsCStringKey(str, mStrLen, OWN);
+}
+
+nsCStringKey::nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mStr(nsnull), mStrLen(0), mOwnership(OWN)
+{
+ nsCAutoString str;
+ nsresult rv = aStream->ReadCString(str);
+ mStr = ToNewCString(str);
+ if (NS_SUCCEEDED(rv))
+ mStrLen = str.Length();
+ *aResult = rv;
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsresult
+nsCStringKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteStringZ(mStr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Copy Constructor
+// We need to free mStr if the object is passed with mOwnership as OWN. As the
+// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
+
+nsStringKey::nsStringKey(const nsStringKey& aKey)
+ : mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
+{
+ if (mOwnership != NEVER_OWN) {
+ PRUint32 len = mStrLen * sizeof(PRUnichar);
+ PRUnichar* str = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(len + sizeof(PRUnichar)));
+ if (!str) {
+ // Pray we don't dangle!
+ mOwnership = NEVER_OWN;
+ } else {
+ // Use memcpy in case there are embedded NULs.
+ memcpy(str, mStr, len);
+ str[mStrLen] = 0;
+ mStr = str;
+ mOwnership = OWN;
+ }
+ }
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const nsAFlatString& str)
+ : mStr(NS_CONST_CAST(PRUnichar*, str.get())),
+ mStrLen(str.Length()),
+ mOwnership(OWN_CLONE)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const nsAString& str)
+ : mStr(ToNewUnicode(str)),
+ mStrLen(str.Length()),
+ mOwnership(OWN)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const PRUnichar* str, PRInt32 strLen, Ownership own)
+ : mStr((PRUnichar*)str), mStrLen(strLen), mOwnership(own)
+{
+ NS_ASSERTION(mStr, "null string key");
+ if (mStrLen == PRUint32(-1))
+ mStrLen = nsCRT::strlen(str);
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::~nsStringKey(void)
+{
+ if (mOwnership == OWN)
+ nsMemory::Free(mStr);
+ MOZ_COUNT_DTOR(nsStringKey);
+}
+
+PRUint32
+nsStringKey::HashCode(void) const
+{
+ return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+}
+
+PRBool
+nsStringKey::Equals(const nsHashKey* aKey) const
+{
+ NS_ASSERTION(aKey->GetKeyType() == StringKey, "mismatched key types");
+ nsStringKey* other = (nsStringKey*)aKey;
+ NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
+ NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
+ if (mStrLen != other->mStrLen)
+ return PR_FALSE;
+ return memcmp(mStr, other->mStr, mStrLen * sizeof(PRUnichar)) == 0;
+}
+
+nsHashKey*
+nsStringKey::Clone() const
+{
+ if (mOwnership == NEVER_OWN)
+ return new nsStringKey(mStr, mStrLen, NEVER_OWN);
+
+ PRUint32 len = (mStrLen+1) * sizeof(PRUnichar);
+ PRUnichar* str = (PRUnichar*)nsMemory::Alloc(len);
+ if (str == NULL)
+ return NULL;
+ memcpy(str, mStr, len);
+ return new nsStringKey(str, mStrLen, OWN);
+}
+
+nsStringKey::nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mStr(nsnull), mStrLen(0), mOwnership(OWN)
+{
+ nsAutoString str;
+ nsresult rv = aStream->ReadString(str);
+ mStr = ToNewUnicode(str);
+ if (NS_SUCCEEDED(rv))
+ mStrLen = str.Length();
+ *aResult = rv;
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsresult
+nsStringKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteWStringZ(mStr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
+// deleted
+
+nsObjectHashtable::nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
+ void* cloneElementClosure,
+ nsHashtableEnumFunc destroyElementFun,
+ void* destroyElementClosure,
+ PRUint32 aSize, PRBool threadSafe)
+ : nsHashtable(aSize, threadSafe),
+ mCloneElementFun(cloneElementFun),
+ mCloneElementClosure(cloneElementClosure),
+ mDestroyElementFun(destroyElementFun),
+ mDestroyElementClosure(destroyElementClosure)
+{
+}
+
+nsObjectHashtable::~nsObjectHashtable()
+{
+ Reset();
+}
+
+
+PLDHashOperator PR_CALLBACK
+nsObjectHashtable::CopyElement(PLDHashTable* table,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg)
+{
+ nsObjectHashtable *newHashtable = (nsObjectHashtable *)arg;
+ HTEntry *entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ void* newElement =
+ newHashtable->mCloneElementFun(entry->key, entry->value,
+ newHashtable->mCloneElementClosure);
+ if (newElement == nsnull)
+ return PL_DHASH_STOP;
+ newHashtable->Put(entry->key, newElement);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable*
+nsObjectHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = PR_FALSE;
+ if (mLock)
+ threadSafe = PR_TRUE;
+ nsObjectHashtable* newHashTable =
+ new nsObjectHashtable(mCloneElementFun, mCloneElementClosure,
+ mDestroyElementFun, mDestroyElementClosure,
+ mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, CopyElement, newHashTable);
+ return newHashTable;
+}
+
+void
+nsObjectHashtable::Reset()
+{
+ nsHashtable::Reset(mDestroyElementFun, mDestroyElementClosure);
+}
+
+PRBool
+nsObjectHashtable::RemoveAndDelete(nsHashKey *aKey)
+{
+ void *value = Remove(aKey);
+ if (value && mDestroyElementFun)
+ return (*mDestroyElementFun)(aKey, value, mDestroyElementClosure);
+ return PR_FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
+
+PRBool PR_CALLBACK
+nsSupportsHashtable::ReleaseElement(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
+ NS_IF_RELEASE(element);
+ return PR_TRUE;
+}
+
+nsSupportsHashtable::~nsSupportsHashtable()
+{
+ Enumerate(ReleaseElement, nsnull);
+}
+
+// Return true if we overwrote something
+
+PRBool
+nsSupportsHashtable::Put(nsHashKey *aKey, nsISupports* aData, nsISupports **value)
+{
+ NS_IF_ADDREF(aData);
+ void *prev = nsHashtable::Put(aKey, aData);
+ nsISupports *old = NS_REINTERPRET_CAST(nsISupports *, prev);
+ if (value) // pass own the ownership to the caller
+ *value = old;
+ else // the caller doesn't care, we do
+ NS_IF_RELEASE(old);
+ return prev != nsnull;
+}
+
+nsISupports *
+nsSupportsHashtable::Get(nsHashKey *aKey)
+{
+ void* data = nsHashtable::Get(aKey);
+ if (!data)
+ return nsnull;
+ nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, data);
+ NS_IF_ADDREF(element);
+ return element;
+}
+
+// Return true if we found something (useful for checks)
+
+PRBool
+nsSupportsHashtable::Remove(nsHashKey *aKey, nsISupports **value)
+{
+ void* data = nsHashtable::Remove(aKey);
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
+ if (value) // caller wants it
+ *value = element;
+ else // caller doesn't care, we do
+ NS_IF_RELEASE(element);
+ return data != nsnull;
+}
+
+PLDHashOperator PR_CALLBACK
+nsSupportsHashtable::EnumerateCopy(PLDHashTable*,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg)
+{
+ nsHashtable *newHashtable = (nsHashtable *)arg;
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, entry->value);
+ NS_IF_ADDREF(element);
+ newHashtable->Put(entry->key, entry->value);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable*
+nsSupportsHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = (mLock != nsnull);
+ nsSupportsHashtable* newHashTable =
+ new nsSupportsHashtable(mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, EnumerateCopy, newHashTable);
+ return newHashTable;
+}
+
+void
+nsSupportsHashtable::Reset()
+{
+ Enumerate(ReleaseElement, nsnull);
+ nsHashtable::Reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h
new file mode 100644
index 00000000..21ce9028
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * 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 "prlock.h"
+#include "nscore.h"
+#include "nsString.h"
+#include "nsISupportsBase.h"
+#include "nsTraceRefcnt.h"
+
+class nsIObjectInputStream;
+class nsIObjectOutputStream;
+
+class nsHashtable;
+class nsStringKey;
+
+class NS_COM 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 PRUint32 HashCode(void) const = 0;
+ virtual PRBool 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 = PR_FALSE,
+ kHashEnumerateNext = PR_TRUE,
+ kHashEnumerateRemove = 2
+};
+
+typedef PRIntn
+(*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
+
+typedef nsresult
+(*PR_CALLBACK 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
+(*PR_CALLBACK nsHashtableFreeEntryFunc)(nsIObjectInputStream *aStream,
+ nsHashKey *aKey,
+ void *aData);
+
+typedef nsresult
+(*PR_CALLBACK nsHashtableWriteDataFunc)(nsIObjectOutputStream *aStream,
+ void *aData);
+
+class NS_COM nsHashtable {
+ protected:
+ // members
+ PRLock* mLock;
+ PLDHashTable mHashtable;
+ PRBool mEnumerating;
+
+ public:
+ nsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
+ virtual ~nsHashtable();
+
+ PRInt32 Count(void) { return mHashtable.entryCount; }
+ PRBool 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 = NULL);
+ void Reset();
+ void Reset(nsHashtableEnumFunc destroyFunc, void* aClosure = NULL);
+
+ 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* (*PR_CALLBACK nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* aClosure);
+
+class NS_COM nsObjectHashtable : public nsHashtable {
+ public:
+ nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
+ void* cloneElementClosure,
+ nsHashtableEnumFunc destroyElementFun,
+ void* destroyElementClosure,
+ PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
+ ~nsObjectHashtable();
+
+ nsHashtable *Clone();
+ void Reset();
+ PRBool RemoveAndDelete(nsHashKey *aKey);
+
+ protected:
+ static PLDHashOperator PR_CALLBACK CopyElement(PLDHashTable* table,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg);
+
+ nsHashtableCloneElementFunc mCloneElementFun;
+ void* mCloneElementClosure;
+ nsHashtableEnumFunc mDestroyElementFun;
+ void* mDestroyElementClosure;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
+
+class nsISupports;
+
+class NS_COM nsSupportsHashtable
+ : private nsHashtable
+{
+ public:
+ typedef PRBool (* PR_CALLBACK EnumFunc) (nsHashKey *aKey, void *aData, void* aClosure);
+
+ nsSupportsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE)
+ : nsHashtable(aSize, threadSafe) {}
+ ~nsSupportsHashtable();
+
+ PRInt32 Count(void) {
+ return nsHashtable::Count();
+ }
+ PRBool Exists(nsHashKey *aKey) {
+ return nsHashtable::Exists (aKey);
+ }
+ PRBool Put(nsHashKey *aKey,
+ nsISupports *aData,
+ nsISupports **value = nsnull);
+ nsISupports* Get(nsHashKey *aKey);
+ PRBool Remove(nsHashKey *aKey, nsISupports **value = nsnull);
+ nsHashtable *Clone();
+ void Enumerate(EnumFunc aEnumFunc, void* aClosure = NULL) {
+ nsHashtable::Enumerate(aEnumFunc, aClosure);
+ }
+ void Reset();
+
+ private:
+ static PRBool PR_CALLBACK ReleaseElement(nsHashKey *, void *, void *);
+ static PLDHashOperator PR_CALLBACK EnumerateCopy(PLDHashTable*,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupportsKey: Where keys are nsISupports objects that get refcounted.
+
+#include "nsISupports.h"
+
+class NS_COM 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);
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mKey);
+ }
+
+ PRBool 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;
+};
+
+
+class nsPRUint32Key : public nsHashKey {
+protected:
+ PRUint32 mKey;
+public:
+ nsPRUint32Key(PRUint32 key) {
+#ifdef DEBUG
+ mKeyType = PRUint32Key;
+#endif
+ mKey = key;
+ }
+
+ PRUint32 HashCode(void) const {
+ return mKey;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ return mKey == ((const nsPRUint32Key *) aKey)->mKey;
+ }
+ nsHashKey *Clone() const {
+ return new nsPRUint32Key(mKey);
+ }
+ PRUint32 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;
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mKey);
+ }
+
+ PRBool 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; }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIDKey: Where keys are nsIDs (e.g. nsIID, nsCID).
+
+#include "nsID.h"
+
+class NS_COM nsIDKey : public nsHashKey {
+ protected:
+ nsID mID;
+
+ public:
+ nsIDKey(const nsIDKey& aKey) : mID(aKey.mID) {
+#ifdef DEBUG
+ mKeyType = IDKey;
+#endif
+ }
+
+ nsIDKey(const nsID &aID) {
+#ifdef DEBUG
+ mKeyType = IDKey;
+#endif
+ mID = aID;
+ }
+
+ PRUint32 HashCode(void) const {
+ return mID.m0;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ NS_ASSERTION(aKey->GetKeyType() == IDKey, "mismatched key types");
+ return (mID.Equals(((const nsIDKey *) aKey)->mID));
+ }
+
+ nsHashKey *Clone() const {
+ return new nsIDKey(mID);
+ }
+
+ nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult);
+ nsresult Write(nsIObjectOutputStream* aStream) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include "nsString.h"
+
+// for null-terminated c-strings
+class NS_COM 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, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
+ nsCStringKey(const nsAFlatCString& str);
+ nsCStringKey(const nsACString& str);
+ ~nsCStringKey(void);
+
+ PRUint32 HashCode(void) const;
+ PRBool 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; }
+ PRUint32 GetStringLength() const { return mStrLen; }
+
+ protected:
+ char* mStr;
+ PRUint32 mStrLen;
+ Ownership mOwnership;
+};
+
+// for null-terminated unicode strings
+class NS_COM 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, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
+ nsStringKey(const nsAFlatString& str);
+ nsStringKey(const nsAString& str);
+ ~nsStringKey(void);
+
+ PRUint32 HashCode(void) const;
+ PRBool 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; }
+ PRUint32 GetStringLength() const { return mStrLen; }
+
+ protected:
+ PRUnichar* mStr;
+ PRUint32 mStrLen;
+ Ownership mOwnership;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl b/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl
new file mode 100644
index 00000000..c937ec4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array interface.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsISimpleEnumerator;
+
+/**
+ * nsIArray
+ *
+ * An indexed collection of elements. Provides basic functionality for
+ * retrieving elements at a specific position, searching for
+ * elements. Indexes are zero-based, such that the last element in the
+ * array is stored at the index length-1.
+ *
+ * For an array which can be modified, see nsIMutableArray below.
+ *
+ * Neither interface makes any attempt to protect the individual
+ * elements from modification. The convention is that the elements of
+ * the array should not be modified. Documentation within a specific
+ * interface should describe variations from this convention.
+ *
+ * It is also convention that if an interface provides access to an
+ * nsIArray, that the array should not be QueryInterfaced to an
+ * nsIMutableArray for modification. If the interface in question had
+ * intended the array to be modified, it would have returned an
+ * nsIMutableArray!
+ *
+ * null is a valid entry in the array, and as such any nsISupports
+ * parameters may be null, except where noted.
+ *
+ * @status UNDER_REVIEW
+ */
+[scriptable, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
+interface nsIArray : nsISupports
+{
+ /**
+ * length
+ *
+ * number of elements in the array.
+ */
+ readonly attribute unsigned long length;
+
+ /**
+ * queryElementAt()
+ *
+ * Retrieve a specific element of the array, and QueryInterface it
+ * to the specified interface. null is a valid result for
+ * this method, but exceptions are thrown in other circumstances
+ *
+ * @param index position of element
+ * @param uuid the IID of the requested interface
+ * @param result the object, QI'd to the requested interface
+ *
+ * @throws NS_ERROR_NO_INTERFACE when an entry exists at the
+ * specified index, but the requested interface is not
+ * available.
+ * @throws NS_ERROR_ILLEGAL_VALUE when index > length-1
+ *
+ */
+ void queryElementAt(in unsigned long index,
+ in nsIIDRef uuid,
+ [iid_is(uuid), retval] out nsQIResult result);
+
+ /**
+ * indexOf()
+ *
+ * Get the position of a specific element. Note that since null is
+ * a valid input, exceptions are used to indicate that an element
+ * is not found.
+ *
+ * @param startIndex The initial element to search in the array
+ * To start at the beginning, use 0 as the
+ * startIndex
+ * @param element The element you are looking for
+ * @returns a number >= startIndex which is the position of the
+ * element in the array.
+ * @throws NS_ERROR_NOT_FOUND if the element was not in the array.
+ */
+ unsigned long indexOf(in unsigned long startIndex,
+ in nsISupports element);
+
+ /**
+ * enumerate the array
+ *
+ * @returns a new enumerator positioned at the start of the array
+ * @throws NS_ERROR_FAILURE if the array is empty (to make it easy
+ * to detect errors)
+ */
+ nsISimpleEnumerator enumerate();
+
+};
+
+/**
+ * nsIMutableArray
+ * A separate set of methods that will act on the array. Consumers of
+ * nsIArray should not QueryInterface to nsIMutableArray unless they
+ * own the array.
+ *
+ * As above, it is legal to add null elements to the array. Note also
+ * that null elements can be created as a side effect of
+ * insertElementAt(). Conversely, if insertElementAt() is never used,
+ * and null elements are never explicitly added to the array, then it
+ * is guaranteed that queryElementAt() will never return a null value.
+ *
+ * Any of these methods may throw NS_ERROR_OUT_OF_MEMORY when the
+ * array must grow to complete the call, but the allocation fails.
+ *
+ * @status UNDER_REVIEW
+ */
+
+[scriptable, uuid(2cd0b2f8-d4dd-48b8-87ba-b0200501f079)]
+interface nsIMutableArray : nsIArray
+{
+ /**
+ * appendElement()
+ *
+ * Append an element at the end of the array.
+ *
+ * @param element The element to append.
+ * @param element Whether or not to store the element using a weak
+ * reference.
+ * @throws NS_ERROR_UNEXPECTED when a weak reference is requested,
+ * but the element does not support
+ * nsIWeakReference.
+ */
+ void appendElement(in nsISupports element, in boolean weak);
+
+ /**
+ * removeElementAt()
+ *
+ * Remove an element at a specific position.
+ * To remove a specific element, use indexOf() to find the index
+ * first, then call removeElementAt().
+ *
+ * @param index the position of the item
+ *
+ */
+ void removeElementAt(in unsigned long index);
+
+ /**
+ * insertElementAt()
+ *
+ * Insert an element at the given position, and move all elements
+ * stored at a higher position up one.
+ *
+ * @param element The element to insert
+ * @param index The position in the array. If the position is
+ * greater than or equal to the length of the array
+ * (@see nsIArray) then the array will grow to
+ * exactly accomadate the index, and the new length
+ * will be index+1. The newly created entries will
+ * be null.
+ *
+ * @throws NS_ERROR_FAILURE when a weak reference is requested,
+ * but the element does not support
+ * nsIWeakReference.
+ */
+ void insertElementAt(in nsISupports element, in unsigned long index, in boolean weak);
+
+ /**
+ * clear()
+ *
+ * clear the entire array, releasing all stored objects
+ */
+ void clear();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl b/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl
new file mode 100644
index 00000000..45eecb4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsISupports.idl"
+
+%{C++
+#include "nsAString.h"
+#include "nsCOMPtr.h"
+%}
+
+/*
+ * Should this really be scriptable? Using atoms from script or proxies
+ * could be dangerous since double-wrapping could lead to loss of
+ * pointer identity.
+ */
+
+[scriptable, uuid(3d1b15b0-93b4-11d1-895b-006008911b81)]
+interface nsIAtom : nsISupports
+{
+ /**
+ * Get the Unicode or UTF8 value for the string
+ */
+ AString toString();
+ AUTF8String toUTF8String();
+
+ /**
+ * Return a pointer to a zero terminated UTF8 string.
+ */
+ [noscript] void getUTF8String([shared, retval] out string aResult);
+
+ /**
+ * Compare the atom to a specific string value
+ * Note that this will NEVER return/throw an error condition.
+ */
+ boolean equals(in AString aString);
+
+ boolean equalsUTF8(in AUTF8String aString);
+
+%{C++
+ // note this is NOT virtual so this won't muck with the vtable!
+ inline PRBool Equals(const nsAString& s) {
+ PRBool result;
+ Equals(s, &result);
+ return result;
+ }
+
+ inline PRBool EqualsUTF8(const nsACString& s) {
+ PRBool result;
+ EqualsUTF8(s, &result);
+ return result;
+ }
+%}
+
+};
+
+
+%{C++
+/*
+ * The three forms of NS_NewAtom and do_GetAtom (for use with
+ * |nsCOMPtr<nsIAtom>|) return the atom for the string given. At any
+ * given time there will always be one atom representing a given string.
+ * Atoms are intended to make string comparison cheaper by simplifying
+ * it to pointer equality. A pointer to the atom that does not own a
+ * reference is not guaranteed to be valid.
+ *
+ * The three forms of NS_NewPermanentAtom and do_GetPermanentAtom return
+ * the atom for the given string and ensure that the atom is permanent.
+ * An atom that is permanent will exist (occupy space at a specific
+ * location in memory) until XPCOM is shut down. The advantage of
+ * permanent atoms is that they do not need to maintain a reference
+ * count, which requires locking and hurts performance.
+ */
+
+
+/**
+ * Find an atom that matches the given UTF-8 string.
+ * The string is assumed to be zero terminated.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const char* aUTF8String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const char* aUTF8String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const char* aUTF8String)
+ { return NS_NewAtom(aUTF8String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const char* aUTF8String)
+ { return NS_NewPermanentAtom(aUTF8String); }
+
+/**
+ * Find an atom that matches the given UTF-8 string.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsACString& aUTF8String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const nsACString& aUTF8String)
+ { return NS_NewAtom(aUTF8String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsACString& aUTF8String)
+ { return NS_NewPermanentAtom(aUTF8String); }
+
+/**
+ * Find an atom that matches the given UTF-16 string.
+ * The string is assumed to be zero terminated.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const PRUnichar* aUTF16String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const PRUnichar* aUTF16String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const PRUnichar* aUTF16String)
+ { return NS_NewAtom(aUTF16String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const PRUnichar* aUTF16String)
+ { return NS_NewPermanentAtom(aUTF16String); }
+
+/**
+ * Find an atom that matches the given UTF-16 string.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsAString& aUTF16String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const nsAString& aUTF16String)
+ { return NS_NewAtom(aUTF16String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsAString& aUTF16String)
+ { return NS_NewPermanentAtom(aUTF16String); }
+
+/**
+ * Return a count of the total number of atoms currently
+ * alive in the system.
+ */
+extern NS_COM nsrefcnt NS_GetNumberOfAtoms(void);
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl b/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl
new file mode 100644
index 00000000..b3a30358
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIAtom.idl"
+
+%{C++
+#define NS_ATOMSERVICE_CID \
+{ /* ed3db3fc-0168-4cab-8818-98f5475a490c */ \
+ 0xed3db3fc, \
+ 0x0168, \
+ 0x4cab, \
+ {0x88, 0x18, 0x98, 0xf5, 0x47, 0x5a, 0x49, 0x0c} }
+
+#define NS_ATOMSERVICE_CONTRACTID "@mozilla.org/atom-service;1"
+#define NS_ATOMSERVICE_CLASSNAME "Atom Service"
+%}
+
+/*
+ * Should this really be scriptable? Using atoms from script or proxies
+ * could be dangerous since double-wrapping could lead to loss of
+ * pointer identity.
+ */
+
+[scriptable, uuid(e5d0d92b-ea45-4622-ab48-302baf2094ee)]
+interface nsIAtomService : nsISupports {
+
+ /**
+ * Version of NS_NewAtom that doesn't require linking against the
+ * XPCOM library. See nsIAtom.idl.
+ */
+ nsIAtom getAtom(in wstring value);
+
+ /**
+ * Version of NS_NewPermanentAtom that doesn't require linking against
+ * the XPCOM library. See nsIAtom.idl.
+ */
+ nsIAtom getPermanentAtom(in wstring value);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h
new file mode 100644
index 00000000..5d02c9cb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIByteBuffer_h___
+#define nsIByteBuffer_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+class nsIInputStream;
+
+#define NS_IBYTE_BUFFER_IID \
+{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+#define NS_IBYTEBUFFER_IID \
+{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+#define NS_BYTEBUFFER_CONTRACTID "@mozilla.org/byte-buffer;1"
+#define NS_BYTEBUFFER_CLASSNAME "Byte Buffer"
+
+/** Interface to a buffer that holds bytes */
+class nsIByteBuffer : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBYTEBUFFER_IID)
+
+ NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
+
+ /** @return length of buffer, i.e. how many bytes are currently in it. */
+ NS_IMETHOD_(PRUint32) GetLength(void) const = 0;
+
+ /** @return number of bytes allocated in the buffer */
+ NS_IMETHOD_(PRUint32) GetBufferSize(void) const = 0;
+
+ /** @return the buffer */
+ NS_IMETHOD_(char*) GetBuffer(void) const = 0;
+
+ /** Grow buffer to aNewSize bytes. */
+ NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize) = 0;
+
+ /** Fill the buffer with data from aStream. Don't grow the buffer, only
+ * read until length of buffer equals buffer size. */
+ NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep) = 0;
+};
+
+#define NS_BYTEBUFFER_CID \
+{ /* a49d5280-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xa49d5280, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+/** Create a new byte buffer using the given buffer size. */
+extern NS_COM nsresult
+NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize = 0);
+
+#endif /* nsIByteBuffer_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl b/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl
new file mode 100644
index 00000000..f97bf970
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl
@@ -0,0 +1,92 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>: |do_QueryElementAt|
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISerializable.idl"
+#include "nsIEnumerator.idl"
+
+[scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)]
+interface nsICollection : nsISerializable
+{
+
+ PRUint32 Count();
+ nsISupports GetElementAt(in PRUint32 index);
+ void QueryElementAt(in PRUint32 index, in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+ void SetElementAt(in PRUint32 index, in nsISupports item);
+ void AppendElement(in nsISupports item);
+ void RemoveElement(in nsISupports item);
+
+ nsIEnumerator Enumerate();
+
+ void Clear();
+
+};
+
+%{C++
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+class NS_COM nsQueryElementAt : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr )
+ : mCollection(aCollection),
+ mIndex(aIndex),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsICollection* mCollection;
+ PRUint32 mIndex;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryElementAt
+do_QueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0 )
+ {
+ return nsQueryElementAt(aCollection, aIndex, aErrorPtr);
+ }
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl
new file mode 100644
index 00000000..7f8824b2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISimpleEnumerator.idl"
+
+%{C++
+#define NS_ENUMERATOR_FALSE 1
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewEmptyEnumerator VBoxNsxpNS_NewEmptyEnumerator
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+extern "C" NS_COM nsresult
+NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult);
+%}
+/*
+ * DO NOT USE THIS INTERFACE. IT IS HORRIBLY BROKEN, USES NS_COMFALSE
+ * AND IS BASICALLY IMPOSSIBLE TO USE CORRECTLY THROUGH PROXIES OR
+ * XPCONNECT. IF YOU SEE NEW USES OF THIS INTERFACE IN CODE YOU ARE
+ * REVIEWING, YOU SHOULD INSIST ON nsISimpleEnumerator.
+ *
+ * DON'T MAKE ME COME OVER THERE.
+ */
+[scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)]
+interface nsIEnumerator : nsISupports {
+ /** First will reset the list. will return NS_FAILED if no items
+ */
+ void first();
+
+ /** Next will advance the list. will return failed if already at end
+ */
+ void next();
+
+ /** CurrentItem will return the CurrentItem item it will fail if the
+ * list is empty
+ */
+ nsISupports currentItem();
+
+ /** return if the collection is at the end. that is the beginning following
+ * a call to Prev and it is the end of the list following a call to next
+ */
+ void isDone();
+};
+
+[uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)]
+interface nsIBidirectionalEnumerator : nsIEnumerator {
+
+ /** Last will reset the list to the end. will return NS_FAILED if no items
+ */
+ void last();
+
+ /** Prev will decrement the list. will return failed if already at beginning
+ */
+ void prev();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl b/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl
new file mode 100644
index 00000000..ca3c6598
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl
@@ -0,0 +1,58 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg <benjamin@smedbergs.us>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Represents an object that can be stored in a hashtable.
+ */
+
+[scriptable, uuid(17e595fa-b57a-4933-bd0f-b1812e8ab188)]
+interface nsIHashable : nsISupports
+{
+ /**
+ * Is this object the equivalent of the other object?
+ */
+ boolean equals(in nsIHashable aOther);
+
+ /**
+ * A generated hashcode for this object. Objects that are equivalent
+ * must have the same hash code. Getting this property should never
+ * throw an exception!
+ */
+ readonly attribute unsigned long hashCode;
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl b/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl
new file mode 100644
index 00000000..d2240f2e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * This interface is implemented by an object that wants
+ * to observe an event corresponding to a topic.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(DB242E01-E4D9-11d2-9DDE-000064657374)]
+interface nsIObserver : nsISupports {
+
+ /**
+ * Observe will be called when there is a notification for the
+ * topic |aTopic|. This assumes that the object implementing
+ * this interface has been registered with an observer service
+ * such as the nsIObserverService.
+ *
+ * If you expect multiple topics/subjects, the impl is
+ * responsible for filtering.
+ *
+ * You should not modify, add, remove, or enumerate
+ * notifications in the implemention of observe.
+ *
+ * @param aSubject : Notification specific interface pointer.
+ * @param aTopic : The notification topic or subject.
+ * @param aData : Notification specific wide string.
+ * subject event.
+ */
+ void observe( in nsISupports aSubject,
+ in string aTopic,
+ in wstring aData );
+
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl b/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl
new file mode 100644
index 00000000..059a903a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIObserver;
+interface nsISimpleEnumerator;
+
+/**
+ * nsIObserverService
+ *
+ * Service allows a client listener (nsIObserver) to register and unregister for
+ * notifications of specific string referenced topic. Service also provides a
+ * way to notify registered listeners and a way to enumerate registered client
+ * listeners.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(D07F5192-E3D1-11d2-8ACD-00105A1B8860)]
+interface nsIObserverService : nsISupports
+{
+
+ /**
+ * AddObserver
+ *
+ * Registers a given listener for a notifications regarding the specified
+ * topic.
+ *
+ * @param anObserve : The interface pointer which will receive notifications.
+ * @param aTopic : The notification topic or subject.
+ * @param ownsWeak : If set to false, the nsIObserverService will hold a
+ * strong reference to |anObserver|. If set to true and
+ * |anObserver| supports the nsIWeakReference interface,
+ * a weak reference will be held. Otherwise an error will be
+ * returned.
+ */
+ void addObserver( in nsIObserver anObserver, in string aTopic, in boolean ownsWeak);
+
+ /**
+ * removeObserver
+ *
+ * Unregisters a given listener from notifications regarding the specified
+ * topic.
+ *
+ * @param anObserver : The interface pointer which will stop recieving
+ * notifications.
+ * @param aTopic : The notification topic or subject.
+ */
+ void removeObserver( in nsIObserver anObserver, in string aTopic );
+
+ /**
+ * notifyObservers
+ *
+ * Notifies all registered listeners of the given topic.
+ *
+ * @param aSubject : Notification specific interface pointer.
+ * @param aTopic : The notification topic or subject.
+ * @param someData : Notification specific wide string.
+ */
+ void notifyObservers( in nsISupports aSubject,
+ in string aTopic,
+ in wstring someData );
+
+ /**
+ * enumerateObservers
+ *
+ * Returns an enumeration of all registered listeners.
+ *
+ * @param aTopic : The notification topic or subject.
+ */
+ nsISimpleEnumerator enumerateObservers( in string aTopic );
+
+
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h
new file mode 100644
index 00000000..773a52ad
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h
@@ -0,0 +1,8 @@
+
+#ifndef __gen_nsIPersistentProperties_h__
+#define __gen_nsIPersistentProperties_h__
+
+// "soft" switch over to an IDL generated header file
+#include "nsIPersistentProperties2.h"
+
+#endif /* __gen_nsIPersistentProperties_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl
new file mode 100644
index 00000000..3d935621
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIProperties.idl"
+#include "nsISimpleEnumerator.idl"
+
+interface nsIInputStream;
+interface nsIOutputStream;
+
+[scriptable, uuid(283EE646-1AEF-11D4-98B3-00C04fA0CE9A)]
+interface nsIPropertyElement : nsISupports {
+ attribute AUTF8String key;
+ attribute AString value;
+};
+
+[scriptable, uuid(1A180F60-93B2-11d2-9B8B-00805F8A16D9)]
+interface nsIPersistentProperties : nsIProperties
+{
+ /**
+ * load a set of name/value pairs from the input stream
+ * names and values should be in UTF8
+ */
+ void load(in nsIInputStream input);
+
+ /**
+ * output the values to the stream - results will be in UTF8
+ */
+ void save(in nsIOutputStream output, in AUTF8String header);
+
+ /**
+ * call subclass() to make future calls to load() set the properties
+ * in this "superclass" instead
+ */
+ void subclass(in nsIPersistentProperties superclass);
+
+ /**
+ * get an enumeration of nsIPropertyElement objects,
+ * which are read-only (i.e. setting properties on the element will
+ * not make changes back into the source nsIPersistentProperties
+ */
+ nsISimpleEnumerator enumerate();
+
+ /**
+ * shortcut to nsIProperty's get() which retrieves a string value
+ * directly (and thus faster)
+ */
+ AString getStringProperty(in AUTF8String key);
+
+ /**
+ * shortcut to nsIProperty's set() which sets a string value
+ * directly (and thus faster)
+ */
+ AString setStringProperty(in AUTF8String key, in AString value);
+};
+
+
+%{C++
+
+//{283EE645-1AEF-11D4-98B3-00C04fA0CE9A}
+#define NS_IPROPERTYELEMENT_CID \
+{ 0x283ee645, 0x1aef, 0x11d4, \
+ { 0x98, 0xb3, 0x0, 0xc0, 0x4f, 0xa0, 0xce, 0x9a } }
+
+#define NS_IPERSISTENTPROPERTIES_CID \
+{ 0x2245e573, 0x9464, 0x11d2, \
+ { 0x9b, 0x8b, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9 } }
+
+#define NS_PERSISTENTPROPERTIES_CONTRACTID "@mozilla.org/persistent-properties;1"
+#define NS_PERSISTENTPROPERTIES_CLASSNAME "Persistent Properties"
+
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl b/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl
new file mode 100644
index 00000000..32a2a057
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl
@@ -0,0 +1,79 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/*
+ * Simple mapping service interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(78650582-4e93-4b60-8e85-26ebd3eb14ca)]
+interface nsIProperties : nsISupports
+{
+ /**
+ * Gets a property with a given name.
+ *
+ * @return NS_ERROR_FAILURE if a property with that name doesn't exist.
+ * @return NS_ERROR_NO_INTERFACE if the found property fails to QI to the
+ * given iid.
+ */
+ void get(in string prop, in nsIIDRef iid,
+ [iid_is(iid),retval] out nsQIResult result);
+
+ /**
+ * Sets a property with a given name to a given value.
+ */
+ void set(in string prop, in nsISupports value);
+
+ /**
+ * Returns true if the property with the given name exists.
+ */
+ boolean has(in string prop);
+
+ /**
+ * Undefines a property.
+ * @return NS_ERROR_FAILURE if a property with that name doesn't
+ * already exist.
+ */
+ void undefine(in string prop);
+
+ /**
+ * Returns an array of the keys.
+ */
+ void getKeys(out PRUint32 count, [array, size_is(count), retval] out string keys);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl b/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl
new file mode 100644
index 00000000..b54577ff
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl
@@ -0,0 +1,77 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsIVariant based Property Bag support. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsISimpleEnumerator.idl"
+
+[scriptable, uuid(6dcf9030-a49f-11d5-910d-0010a4e73d9a)]
+interface nsIProperty : nsISupports
+{
+ /**
+ * Get the name of the property.
+ */
+ readonly attribute AString name;
+
+ /**
+ * Get the value of the property.
+ */
+ readonly attribute nsIVariant value;
+};
+
+[scriptable, uuid(bfcd37b0-a49f-11d5-910d-0010a4e73d9a)]
+interface nsIPropertyBag : nsISupports
+{
+ /**
+ * Get a nsISimpleEnumerator whose elements are nsIProperty objects.
+ */
+ readonly attribute nsISimpleEnumerator enumerator;
+
+ /**
+ * Get a property value for the given name.
+ * @return NS_ERROR_FAILURE if a property with that name doesn't
+ * exist.
+ */
+ nsIVariant getProperty(in AString name);
+};
+
+// We can add nsIWritableProperty and nsIWritablePropertyBag when we need them.
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl
new file mode 100644
index 00000000..5402890e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIMemory.idl"
+
+/**
+ *
+ * nsIRecyclingAllocator: A wrapper for the nsRecyclingAllocator
+ *
+ * Holds allocations and reuses them for subsequent allocs.
+ * Thread safe and uses a timer to release freelist.
+ *
+ * @status UNDER-DEVELOPMENT
+ */
+
+[scriptable, uuid(d064a04c-9cee-4319-be31-64d565bccba9)]
+interface nsIRecyclingAllocator : nsIMemory
+{
+ void init(in size_t nblocks, in size_t recycleAfter, in string id);
+};
+
+%{C++
+#define NS_RECYCLINGALLOCATOR_CID \
+{ /* ac07ed4c-bf17-4976-a15c-d2194db3b1bf */ \
+ 0xac07ed4c, \
+ 0xbf17, \
+ 0x4976, \
+ {0xa1, 0x5c, 0xd2, 0x19, 0x4d, 0xb3, 0xb1, 0xbf} }
+
+#define NS_RECYCLINGALLOCATOR_CLASSNAME "Recycling Allocator"
+
+#define NS_RECYCLINGALLOCATOR_CONTRACTID "@mozilla.org/recycling-allocator;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl b/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl
new file mode 100644
index 00000000..907c4824
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIObjectInputStream;
+interface nsIObjectOutputStream;
+
+[scriptable, uuid(91cca981-c26d-44a8-bebe-d9ed4891503a)]
+interface nsISerializable : nsISupports
+{
+ /**
+ * Initialize the object implementing nsISerializable, which must have
+ * been freshly constructed via CreateInstance. All data members that
+ * can't be set to default values must have been serialized by write,
+ * and should be read from aInputStream in the same order by this method.
+ */
+ void read(in nsIObjectInputStream aInputStream);
+
+ /**
+ * Serialize the object implementing nsISerializable to aOutputStream, by
+ * writing each data member that must be recovered later to reconstitute
+ * a working replica of this object, in a canonical member and byte order,
+ * to aOutputStream.
+ *
+ * NB: a class that implements nsISerializable *must* also implement
+ * nsIClassInfo, in particular nsIClassInfo::GetClassID.
+ */
+ void write(in nsIObjectOutputStream aOutputStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl
new file mode 100644
index 00000000..3f0efbf5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Used to enumerate over elements defined by its implementor.
+ * Although hasMoreElements() can be called independently of getNext(),
+ * getNext() must be pre-ceeded by a call to hasMoreElements(). There is
+ * no way to "reset" an enumerator, once you obtain one.
+ *
+ * @status FROZEN
+ * @version 1.0
+ */
+
+[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
+interface nsISimpleEnumerator : nsISupports {
+ /**
+ * Called to determine whether or not the enumerator has
+ * any elements that can be returned via getNext(). This method
+ * is generally used to determine whether or not to initiate or
+ * continue iteration over the enumerator, though it can be
+ * called without subsequent getNext() calls. Does not affect
+ * internal state of enumerator.
+ *
+ * @see getNext()
+ * @return PR_TRUE if there are remaining elements in the enumerator.
+ * PR_FALSE if there are no more elements in the enumerator.
+ */
+ boolean hasMoreElements();
+
+ /**
+ * Called to retrieve the next element in the enumerator. The "next"
+ * element is the first element upon the first call. Must be
+ * pre-ceeded by a call to hasMoreElements() which returns PR_TRUE.
+ * This method is generally called within a loop to iterate over
+ * the elements in the enumerator.
+ *
+ * @see hasMoreElements()
+ * @return NS_OK if the call succeeded in returning a non-null
+ * value through the out parameter.
+ * NS_ERROR_FAILURE if there are no more elements
+ * to enumerate.
+ * @return the next element in the enumeration.
+ */
+ nsISupports getNext();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl
new file mode 100644
index 00000000..a7ac9131
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl
@@ -0,0 +1,58 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Used to enumerate over an ordered list of strings.
+ */
+
+[scriptable, uuid(50d3ef6c-9380-4f06-9fb2-95488f7d141c)]
+interface nsIStringEnumerator : nsISupports
+{
+ boolean hasMore();
+ AString getNext();
+};
+
+[scriptable, uuid(9bdf1010-3695-4907-95ed-83d0410ec307)]
+interface nsIUTF8StringEnumerator : nsISupports
+{
+ boolean hasMore();
+ AUTF8String getNext();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl
new file mode 100644
index 00000000..bce9f4bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+#include "nsICollection.idl"
+
+/*
+ * This entire interface is deprecated and should not be used.
+ * See nsIArray and nsIMutableArray for the new implementations.
+ *
+ * http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=3D779491.3050506%40netscape.com&rnum=2
+ * http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=al8412%245ab2%40ripley.netscape.com&rnum=8
+ */
+
+native nsISupportsArrayEnumFunc(nsISupportsArrayEnumFunc);
+
+%{C++
+
+class nsIBidirectionalEnumerator;
+
+#define NS_SUPPORTSARRAY_CID \
+{ /* bda17d50-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xbda17d50, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+#define NS_SUPPORTSARRAY_CONTRACTID "@mozilla.org/supports-array;1"
+#define NS_SUPPORTSARRAY_CLASSNAME "Supports Array"
+
+// Enumerator callback function. Return PR_FALSE to stop
+typedef PRBool (*nsISupportsArrayEnumFunc)(nsISupports* aElement, void *aData);
+
+%}
+
+[scriptable, uuid(791eafa0-b9e6-11d1-8031-006008159b5a)]
+interface nsISupportsArray : nsICollection {
+
+ [notxpcom] boolean Equals([const] in nsISupportsArray other);
+
+ [notxpcom] nsISupports ElementAt(in unsigned long aIndex);
+
+ [notxpcom] long IndexOf([const] in nsISupports aPossibleElement);
+ [notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement,
+ in unsigned long aStartIndex);
+ [notxpcom] long LastIndexOf([const] in nsISupports aPossibleElement);
+
+ // xpcom-compatible versions
+ long GetIndexOf(in nsISupports aPossibleElement);
+ long GetIndexOfStartingAt(in nsISupports aPossibleElement,
+ in unsigned long aStartIndex);
+ long GetLastIndexOf(in nsISupports aPossibleElement);
+
+ [notxpcom] boolean InsertElementAt(in nsISupports aElement,
+ in unsigned long aIndex);
+ [notxpcom] boolean ReplaceElementAt(in nsISupports aElement,
+ in unsigned long aIndex);
+
+ [notxpcom] boolean RemoveElementAt(in unsigned long aIndex);
+ [notxpcom] boolean RemoveLastElement([const] in nsISupports aElement);
+
+ // xpcom-compatible versions
+ void DeleteLastElement(in nsISupports aElement);
+ void DeleteElementAt(in unsigned long aIndex);
+
+ [notxpcom] boolean AppendElements(in nsISupportsArray aElements);
+
+ void Compact();
+
+ [notxpcom, noscript]
+ boolean EnumerateForwards(in nsISupportsArrayEnumFunc aFunc,
+ in voidPtr aData);
+ [notxpcom, noscript]
+ boolean EnumerateBackwards(in nsISupportsArrayEnumFunc aFunc,
+ in voidPtr aData);
+
+ nsISupportsArray clone();
+
+ [notxpcom] boolean MoveElement(in long aFrom,
+ in long aTo);
+
+ [notxpcom] boolean InsertElementsAt(in nsISupportsArray aOther,
+ in unsigned long aIndex);
+
+ [notxpcom] boolean RemoveElementsAt(in unsigned long aIndex,
+ in unsigned long aCount);
+
+ [notxpcom] boolean SizeTo(in long aSize);
+
+};
+
+%{C++
+
+// Construct and return a default implementation of nsISupportsArray:
+extern NS_COM nsresult
+NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult);
+
+// Construct and return a default implementation of an enumerator for nsISupportsArrays:
+extern NS_COM nsresult
+NS_NewISupportsArrayEnumerator(nsISupportsArray* array,
+ nsIBidirectionalEnumerator* *aInstancePtrResult);
+
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl
new file mode 100644
index 00000000..f1d8bce1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsISupportsIterators.idl --- IDL defining general purpose iterators */
+
+
+#include "nsISupports.idl"
+
+
+ /*
+ ...
+ */
+
+
+ /**
+ * ...
+ */
+[scriptable, uuid(7330650e-1dd2-11b2-a0c2-9ff86ee97bed)]
+interface nsIOutputIterator : nsISupports
+ {
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(85585e12-1dd2-11b2-a930-f6929058269a)]
+interface nsIInputIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(8da01646-1dd2-11b2-98a7-c7009045be7e)]
+interface nsIForwardIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(948defaa-1dd1-11b2-89f6-8ce81f5ebda9)]
+interface nsIBidirectionalIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Move this iterator to the previous position in the underlying container or sequence.
+ */
+ void stepBackward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(9bd6fdb0-1dd1-11b2-9101-d15375968230)]
+interface nsIRandomAccessIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Retrieve (and |AddRef()|) an element at some offset from where this iterator currently points.
+ * The offset may be negative. |getElementAt(0)| is equivalent to |getElement()|.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ * @result a new reference to the indicated element (if any)
+ */
+ nsISupports getElementAt( in PRInt32 anOffset );
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position |anOffset| away from that currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ * |putElementAt(0, obj)| is equivalent to |putElement(obj)|.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElementAt( in PRInt32 anOffset, in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Move this iterator by |anOffset| positions in the underlying container or sequence.
+ * |anOffset| may be negative. |stepForwardBy(1)| is equivalent to |stepForward()|.
+ * |stepForwardBy(0)| is a no-op.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ */
+ void stepForwardBy( in PRInt32 anOffset );
+
+ /**
+ * Move this iterator to the previous position in the underlying container or sequence.
+ */
+ void stepBackward();
+
+ /**
+ * Move this iterator backwards by |anOffset| positions in the underlying container or sequence.
+ * |anOffset| may be negative. |stepBackwardBy(1)| is equivalent to |stepBackward()|.
+ * |stepBackwardBy(n)| is equivalent to |stepForwardBy(-n)|. |stepBackwardBy(0)| is a no-op.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ */
+ void stepBackwardBy( in PRInt32 anOffset );
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+%{C++
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl
new file mode 100644
index 00000000..680e5599
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl
@@ -0,0 +1,304 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsISupports wrappers for single primitive pieces of data. */
+
+#include "nsISupports.idl"
+
+/**
+ * Primitive base interface.
+ *
+ * These first three are pointer types and do data copying
+ * using the nsIMemory. Be careful!
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d0d4b136-1dd1-11b2-9371-f0727ef827c0)]
+interface nsISupportsPrimitive : nsISupports
+{
+ const unsigned short TYPE_ID = 1;
+ const unsigned short TYPE_CSTRING = 2;
+ const unsigned short TYPE_STRING = 3;
+ const unsigned short TYPE_PRBOOL = 4;
+ const unsigned short TYPE_PRUINT8 = 5;
+ const unsigned short TYPE_PRUINT16 = 6;
+ const unsigned short TYPE_PRUINT32 = 7;
+ const unsigned short TYPE_PRUINT64 = 8;
+ const unsigned short TYPE_PRTIME = 9;
+ const unsigned short TYPE_CHAR = 10;
+ const unsigned short TYPE_PRINT16 = 11;
+ const unsigned short TYPE_PRINT32 = 12;
+ const unsigned short TYPE_PRINT64 = 13;
+ const unsigned short TYPE_FLOAT = 14;
+ const unsigned short TYPE_DOUBLE = 15;
+ const unsigned short TYPE_VOID = 16;
+ const unsigned short TYPE_INTERFACE_POINTER = 17;
+
+ readonly attribute unsigned short type;
+};
+
+/**
+ * Scriptable storage for nsID structures
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d18290a0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsID : nsISupportsPrimitive
+{
+ attribute nsIDPtr data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for ASCII strings
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d65ff270-4a1c-11d3-9890-006008962422)]
+interface nsISupportsCString : nsISupportsPrimitive
+{
+ attribute ACString data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for Unicode strings
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d79dc970-4a1c-11d3-9890-006008962422)]
+interface nsISupportsString : nsISupportsPrimitive
+{
+ attribute AString data;
+ wstring toString();
+};
+
+/**
+ * The rest are truly primitive and are passed by value
+ */
+
+/**
+ * Scriptable storage for booleans
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(ddc3b490-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRBool : nsISupportsPrimitive
+{
+ attribute PRBool data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 8-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(dec2e4e0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint8 : nsISupportsPrimitive
+{
+ attribute PRUint8 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for unsigned 16-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(dfacb090-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint16 : nsISupportsPrimitive
+{
+ attribute PRUint16 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for unsigned 32-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e01dc470-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint32 : nsISupportsPrimitive
+{
+ attribute PRUint32 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 64-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e13567c0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint64 : nsISupportsPrimitive
+{
+ attribute PRUint64 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for NSPR date/time values
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e2563630-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRTime : nsISupportsPrimitive
+{
+ attribute PRTime data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for single character values
+ * (often used to store an ASCII character)
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e2b05e40-4a1c-11d3-9890-006008962422)]
+interface nsISupportsChar : nsISupportsPrimitive
+{
+ attribute char data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 16-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e30d94b0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt16 : nsISupportsPrimitive
+{
+ attribute PRInt16 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 32-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e36c5250-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt32 : nsISupportsPrimitive
+{
+ attribute PRInt32 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 64-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e3cb0ff0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt64 : nsISupportsPrimitive
+{
+ attribute PRInt64 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for floating point numbers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(abeaa390-4ac0-11d3-baea-00805f8a5dd7)]
+interface nsISupportsFloat : nsISupportsPrimitive
+{
+ attribute float data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for doubles
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(b32523a0-4ac0-11d3-baea-00805f8a5dd7)]
+interface nsISupportsDouble : nsISupportsPrimitive
+{
+ attribute double data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for generic pointers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(464484f0-568d-11d3-baf8-00805f8a5dd7)]
+interface nsISupportsVoid : nsISupportsPrimitive
+{
+ [noscript] attribute voidPtr data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for other XPCOM objects
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(995ea724-1dd1-11b2-9211-c21bdd3e7ed0)]
+interface nsISupportsInterfacePointer : nsISupportsPrimitive
+{
+ attribute nsISupports data;
+ attribute nsIDPtr dataIID;
+
+ string toString();
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl b/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl
new file mode 100644
index 00000000..f0495a35
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl
@@ -0,0 +1,242 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#ifdef MOZ_TIMELINE
+%}
+
+/**
+ * nsITimelineService is used to constuct a timeline of program
+ * execution. The timeline is output to a file, either stderr or the
+ * value of the environment variable NS_TIMELINE_LOG_FILE. On the
+ * Mac, the timeline is output to the file named "timeline.txt". The
+ * reason it's different on the Mac is that the Mac environment
+ * initialization code happens after timeline initialization code.
+ *
+ * If NS_TIMELINE_INIT_TIME is set in the environment, that will be
+ * used as the time of startup; otherwise the current time when mark()
+ * is first called will be used.
+ *
+ * mark() is used to put marks on the timeline.
+ *
+ * indent() and outdent() are used to format the timeline a bit to
+ * show nesting. This doesn't produce perfect results in the face of
+ * asychrony and multiple threads.
+ *
+ * enter() and leave() are convenience functions that add marks to the
+ * timeline and do indentation.
+ *
+ * startTimer() and stopTimer() control named stop watches. If
+ * startTimer() is called more than once, an equal number of
+ * stopTimer() calls are needed to actually stop the timer. This
+ * makes these timers slightly useful in a threaded environment.
+ *
+ * markTimer() puts a mark on the timeline containing the total for
+ * the named timer.
+ *
+ * Don't use nsITimelineService in C++ code; use the NS_TIMELINE
+ * macros instead. nsITimelineService exists so that JavaScript code
+ * can mark the timeline.
+ */
+[scriptable, uuid(93276790-3daf-11d5-b67d-000064657374)]
+interface nsITimelineService : nsISupports
+{
+ /**
+ * mark()
+ * Print "<elapsed time>: <text>\n" in the timeline log file.
+ */
+ void mark(in string text);
+
+ /**
+ * causes subsequent marks to be indented for a more readable
+ * report.
+ */
+ void indent();
+
+ /**
+ * Causes subsequent marks to be outdented.
+ */
+ void outdent();
+
+ /**
+ * enter/leave bracket code with "<text>..." and "...<text>" as
+ * well as indentation.
+ */
+ void enter(in string text);
+ void leave(in string text);
+
+ void startTimer(in string timerName);
+
+ void stopTimer(in string timerName);
+
+ void markTimer(in string timerName);
+
+ void resetTimer(in string timerName);
+
+ // Mark a timer, plus an additional comment
+ void markTimerWithComment(in string timerName, in string comment);
+};
+
+%{C++
+#endif /* MOZ_TIMELINE */
+%}
+
+
+%{C++
+
+#ifdef MOZ_TIMELINE
+
+/*
+ * These are equivalent to the corresponding nsITimelineService
+ * methods, and can be called before XPCOM is initialized.
+ */
+extern "C" NS_COM nsresult NS_TimelineMark(const char *text, ...);
+extern "C" NS_COM nsresult NS_TimelineForceMark(const char *text, ...);
+extern "C" NS_COM nsresult NS_TimelineStartTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineStopTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineResetTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineMarkTimer(const char *timerName, const char *str=nsnull);
+extern "C" NS_COM nsresult NS_TimelineIndent();
+extern "C" NS_COM nsresult NS_TimelineOutdent();
+extern "C" NS_COM nsresult NS_TimelineEnter(const char *text);
+extern "C" NS_COM nsresult NS_TimelineLeave(const char *text);
+
+/*
+ * Use these macros for the above calls so we can easily compile them
+ * out.
+ */
+#define NS_TIMELINE_MARK(text) NS_TimelineMark(text)
+#define NS_TIMELINE_MARKV(args) NS_TimelineMark args
+#define NS_TIMELINE_INDENT() NS_TimelineIndent()
+#define NS_TIMELINE_OUTDENT() NS_TimelineOutdent()
+#define NS_TIMELINE_ENTER(text) NS_TimelineEnter(text)
+#define NS_TIMELINE_LEAVE(text) NS_TimelineLeave(text)
+#define NS_TIMELINE_START_TIMER(timerName) NS_TimelineStartTimer(timerName)
+#define NS_TIMELINE_STOP_TIMER(timerName) NS_TimelineStopTimer(timerName)
+#define NS_TIMELINE_MARK_TIMER(timerName) NS_TimelineMarkTimer(timerName)
+#define NS_TIMELINE_RESET_TIMER(timerName) NS_TimelineResetTimer(timerName)
+#define NS_TIMELINE_MARK_TIMER1(timerName, str) NS_TimelineMarkTimer(timerName, str)
+
+/*
+ * Helper class to time functions. Use only static strings.
+ */
+class nsFunctionTimer {
+public:
+ const char *mTimer;
+ PRBool mMark;
+ const char *mMarkStr;
+ nsFunctionTimer(const char *timer, PRBool mark = PR_TRUE, const char *markStr = nsnull)
+ : mTimer(timer), mMark(mark), mMarkStr(markStr)
+ {
+ NS_TIMELINE_START_TIMER(mTimer);
+ }
+
+ ~nsFunctionTimer()
+ {
+ NS_TIMELINE_STOP_TIMER(mTimer);
+ if (mMark)
+ if (mMarkStr)
+ NS_TIMELINE_MARK_TIMER1(mTimer, mMarkStr);
+ else
+ NS_TIMELINE_MARK_TIMER(mTimer);
+ }
+};
+
+/*
+ * NS_TIMELINE_MARK_ macros for various data types. Each of these
+ * macros replaces "%s" in its "text" argument with a string
+ * representation of its last argument.
+ *
+ * Please feel free to add more NS_TIMELINE_MARK_ macros for
+ * various data types so that code using NS_TIMELINE is uncluttered.
+ * Don't forget the empty versions in the #else section below for
+ * non-timeline builds.
+ */
+#define NS_TIMELINE_MARK_URI(text, uri) \
+ { \
+ nsCAutoString spec; \
+ if (uri) { \
+ uri->GetSpec(spec); \
+ } \
+ if (!spec.IsEmpty()) { \
+ NS_TimelineMark(text, spec.get()); \
+ } else { \
+ NS_TimelineMark(text, "??"); \
+ } \
+ }
+
+#define NS_TIMELINE_MARK_CHANNEL(text, channel) \
+ { \
+ nsCOMPtr<nsIURI> uri; \
+ if (channel) { \
+ channel->GetURI(getter_AddRefs(uri)); \
+ } \
+ NS_TIMELINE_MARK_URI(text, uri); \
+ }
+
+#define NS_TIMELINE_MARK_LOADER(text, loader) \
+ { \
+ nsCOMPtr<nsIRequest> request; \
+ loader->GetRequest(getter_AddRefs(request)); \
+ nsCOMPtr<nsIChannel> channel(do_QueryInterface(request)); \
+ NS_TIMELINE_MARK_CHANNEL(text, channel); \
+ }
+#define NS_TIMELINE_MARK_FUNCTION(timer) nsFunctionTimer functionTimer(timer)
+#define NS_TIMELINE_MARK_FUNCTION1(timer, str) nsFunctionTimer functionTimer(timer, PR_TRUE, str)
+#define NS_TIMELINE_TIME_FUNCTION(timer) nsFunctionTimer functionTimer(timer, PR_FALSE) /* no mark, only time */
+
+#else /* !defined(MOZ_TIMELINE) */
+#define NS_TIMELINE_MARK(text)
+#define NS_TIMELINE_MARKV(args)
+#define NS_TIMELINE_INDENT()
+#define NS_TIMELINE_OUTDENT()
+#define NS_TIMELINE_START_TIMER(timerName)
+#define NS_TIMELINE_STOP_TIMER(timerName)
+#define NS_TIMELINE_MARK_TIMER(timerName)
+#define NS_TIMELINE_RESET_TIMER(timerName)
+#define NS_TIMELINE_MARK_TIMER1(timerName, str)
+#define NS_TIMELINE_ENTER(text)
+#define NS_TIMELINE_LEAVE(text)
+#define NS_TIMELINE_MARK_URI(text, uri)
+#define NS_TIMELINE_MARK_FUNCTION(timer)
+#define NS_TIMELINE_TIME_FUNCTION(timer)
+#define NS_TIMELINE_MARK_CHANNEL(text, channel)
+#define NS_TIMELINE_MARK_LOADER(text, loader);
+#endif /* defined(MOZ_TIMELINE) */
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h
new file mode 100644
index 00000000..dae89021
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsIUnicharBuffer_h___
+#define nsIUnicharBuffer_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+#define NS_IUNICHARBUFFER_IID \
+{ 0x14cf6970, 0x93b5, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+
+/// Interface to a buffer that holds unicode characters
+class nsIUnicharBuffer : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IUNICHARBUFFER_IID);
+
+ NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
+ NS_IMETHOD_(PRInt32) GetLength() const = 0;
+ NS_IMETHOD_(PRInt32) GetBufferSize() const = 0;
+ NS_IMETHOD_(PRUnichar*) GetBuffer() const = 0;
+ NS_IMETHOD_(PRBool) Grow(PRInt32 aNewSize) = 0;
+};
+
+/// Factory method for nsIUnicharBuffer.
+extern NS_COM nsresult
+NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize = 0);
+
+#define NS_UNICHARBUFFER_CID \
+{ /* c81fd8f0-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xc81fd8f0, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+#endif /* nsIUnicharBuffer_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl b/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl
new file mode 100644
index 00000000..2c9d9e96
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl
@@ -0,0 +1,188 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsISupports.idl"
+
+[scriptable,uuid(4d12e540-83d7-11d5-90ed-0010a4e73d9a)]
+interface nsIDataType : nsISupports
+{
+ // These MUST match the declarations in xpt_struct.h.
+ // Otherwise the world is likely to explode.
+ // From xpt_struct.h ...
+ const PRUint16 VTYPE_INT8 = 0; // TD_INT8 = 0,
+ const PRUint16 VTYPE_INT16 = 1; // TD_INT16 = 1,
+ const PRUint16 VTYPE_INT32 = 2; // TD_INT32 = 2,
+ const PRUint16 VTYPE_INT64 = 3; // TD_INT64 = 3,
+ const PRUint16 VTYPE_UINT8 = 4; // TD_UINT8 = 4,
+ const PRUint16 VTYPE_UINT16 = 5; // TD_UINT16 = 5,
+ const PRUint16 VTYPE_UINT32 = 6; // TD_UINT32 = 6,
+ const PRUint16 VTYPE_UINT64 = 7; // TD_UINT64 = 7,
+ const PRUint16 VTYPE_FLOAT = 8; // TD_FLOAT = 8,
+ const PRUint16 VTYPE_DOUBLE = 9; // TD_DOUBLE = 9,
+ const PRUint16 VTYPE_BOOL = 10; // TD_BOOL = 10,
+ const PRUint16 VTYPE_CHAR = 11; // TD_CHAR = 11,
+ const PRUint16 VTYPE_WCHAR = 12; // TD_WCHAR = 12,
+ const PRUint16 VTYPE_VOID = 13; // TD_VOID = 13,
+ const PRUint16 VTYPE_ID = 14; // TD_PNSIID = 14,
+ const PRUint16 VTYPE_DOMSTRING = 15; // TD_DOMSTRING = 15,
+ const PRUint16 VTYPE_CHAR_STR = 16; // TD_PSTRING = 16,
+ const PRUint16 VTYPE_WCHAR_STR = 17; // TD_PWSTRING = 17,
+ const PRUint16 VTYPE_INTERFACE = 18; // TD_INTERFACE_TYPE = 18,
+ const PRUint16 VTYPE_INTERFACE_IS = 19; // TD_INTERFACE_IS_TYPE = 19,
+ const PRUint16 VTYPE_ARRAY = 20; // TD_ARRAY = 20,
+ const PRUint16 VTYPE_STRING_SIZE_IS = 21; // TD_PSTRING_SIZE_IS = 21,
+ const PRUint16 VTYPE_WSTRING_SIZE_IS = 22; // TD_PWSTRING_SIZE_IS = 22,
+ const PRUint16 VTYPE_UTF8STRING = 23; // TD_UTF8STRING = 23,
+ const PRUint16 VTYPE_CSTRING = 24; // TD_CSTRING = 24,
+ const PRUint16 VTYPE_ASTRING = 25; // TD_ASTRING = 25,
+ const PRUint16 VTYPE_EMPTY_ARRAY = 254;
+ const PRUint16 VTYPE_EMPTY = 255;
+};
+
+
+/**
+ * XPConnect has magic to transparently convert between nsIVariant and JS types.
+ * We mark the interface [scriptable] so that JS can use methods
+ * that refer to this interface. But we mark all the methods and attributes
+ * [noscript] since any nsIVariant object will be automatically converted to a
+ * JS type anyway.
+ */
+
+[scriptable, uuid(6c9eb060-8c6a-11d5-90f3-0010a4e73d9a)]
+interface nsIVariant : nsISupports
+{
+ [noscript] readonly attribute PRUint16 dataType;
+
+ [noscript] PRUint8 getAsInt8();
+ [noscript] PRInt16 getAsInt16();
+ [noscript] PRInt32 getAsInt32();
+ [noscript] PRInt64 getAsInt64();
+ [noscript] PRUint8 getAsUint8();
+ [noscript] PRUint16 getAsUint16();
+ [noscript] PRUint32 getAsUint32();
+ [noscript] PRUint64 getAsUint64();
+ [noscript] float getAsFloat();
+ [noscript] double getAsDouble();
+ [noscript] PRBool getAsBool();
+ [noscript] char getAsChar();
+ [noscript] wchar getAsWChar();
+ [notxpcom] nsresult getAsID(out nsID retval);
+ [noscript] AString getAsAString();
+ [noscript] DOMString getAsDOMString();
+ [noscript] ACString getAsACString();
+ [noscript] AUTF8String getAsAUTF8String();
+ [noscript] string getAsString();
+ [noscript] wstring getAsWString();
+ [noscript] nsISupports getAsISupports();
+
+ [noscript] void getAsInterface(out nsIIDPtr iid,
+ [iid_is(iid), retval] out nsQIResult iface);
+
+ [notxpcom] nsresult getAsArray(out PRUint16 type, out nsIID iid,
+ out PRUint32 count, out voidPtr ptr);
+
+ [noscript] void getAsStringWithSize(out PRUint32 size,
+ [size_is(size), retval] out string str);
+
+ [noscript] void getAsWStringWithSize(out PRUint32 size,
+ [size_is(size), retval] out wstring str);
+};
+
+/**
+ * An object that implements nsIVariant may or may NOT also implement this
+ * nsIWritableVariant.
+ *
+ * If the 'writable' attribute is false then attempts to call any of the 'set'
+ * methods can be expected to fail. Setting the 'writable' attribute may or
+ * may not succeed.
+ *
+ */
+
+[scriptable, uuid(5586a590-8c82-11d5-90f3-0010a4e73d9a)]
+interface nsIWritableVariant : nsIVariant
+{
+ attribute PRBool writable;
+
+ void setAsInt8(in PRUint8 aValue);
+ void setAsInt16(in PRInt16 aValue);
+ void setAsInt32(in PRInt32 aValue);
+ void setAsInt64(in PRInt64 aValue);
+ void setAsUint8(in PRUint8 aValue);
+ void setAsUint16(in PRUint16 aValue);
+ void setAsUint32(in PRUint32 aValue);
+ void setAsUint64(in PRUint64 aValue);
+ void setAsFloat(in float aValue);
+ void setAsDouble(in double aValue);
+ void setAsBool(in PRBool aValue);
+ void setAsChar(in char aValue);
+ void setAsWChar(in wchar aValue);
+ void setAsID(in nsIDRef aValue);
+ void setAsAString(in AString aValue);
+ void setAsDOMString(in DOMString aValue);
+ void setAsACString(in ACString aValue);
+ void setAsAUTF8String(in AUTF8String aValue);
+ void setAsString(in string aValue);
+ void setAsWString(in wstring aValue);
+ void setAsISupports(in nsISupports aValue);
+
+ void setAsInterface(in nsIIDRef iid,
+ [iid_is(iid)] in nsQIResult iface);
+
+ [noscript] void setAsArray(in PRUint16 type, in nsIIDPtr iid,
+ in PRUint32 count, in voidPtr ptr);
+
+ void setAsStringWithSize(in PRUint32 size,
+ [size_is(size)] in string str);
+
+ void setAsWStringWithSize(in PRUint32 size,
+ [size_is(size)] in wstring str);
+
+ void setAsVoid();
+ void setAsEmpty();
+ void setAsEmptyArray();
+
+ void setFromVariant(in nsIVariant aValue);
+};
+
+%{C++
+// The contractID for the generic implementation built in to xpcom.
+#define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsInt64.h b/src/libs/xpcom18a4/xpcom/ds/nsInt64.h
new file mode 100644
index 00000000..c7421548
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsInt64.h
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsInt64_h__
+#define nsInt64_h__
+
+#include "prlong.h"
+#include "nscore.h"
+
+/**
+ * This class encapsulates full 64-bit integer functionality and
+ * provides simple arithmetic and conversion operations.
+ */
+
+// If you ever decide that you need to add a non-inline method to this
+// class, be sure to change the class declaration to "class NS_BASE
+// nsInt64".
+
+template<class T>
+class nsTInt64
+{
+public: //XXX should be private
+ T mValue;
+
+public:
+ /**
+ * Construct a new 64-bit integer.
+ */
+ nsTInt64(void) : mValue(LL_ZERO) {
+ }
+
+ /**
+ * Construct a new 64-bit integer from a 32-bit signed integer
+ */
+ nsTInt64(const PRInt32 aInt32) {
+ LL_I2L(mValue, aInt32);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a 32-bit unsigned integer
+ */
+ nsTInt64(const PRUint32 aUint32) {
+ LL_UI2L(mValue, aUint32);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a floating point value.
+ */
+ nsTInt64(const PRFloat64 aFloat64) {
+ LL_D2L(mValue, aFloat64);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a native 64-bit integer
+ */
+ nsTInt64(const T aInt64) : mValue(aInt64) {
+ }
+
+ /**
+ * Construct a new 64-bit integer from another 64-bit integer
+ */
+ nsTInt64(const nsTInt64& aObject) : mValue(aObject.mValue) {
+ }
+
+ // ~nsTInt64(void) -- XXX destructor unnecessary
+
+ /**
+ * Assign a 64-bit integer to another 64-bit integer
+ */
+ const nsTInt64& operator =(const nsTInt64& aObject) {
+ mValue = aObject.mValue;
+ return *this;
+ }
+
+ /**
+ * Convert a 64-bit integer to a signed 32-bit value
+ */
+ operator PRInt32(void) const {
+ PRInt32 result;
+ LL_L2I(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to an unsigned 32-bit value
+ */
+ operator PRUint32(void) const {
+ PRUint32 result;
+ LL_L2UI(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to a floating point value
+ */
+ operator PRFloat64(void) const {
+ PRFloat64 result;
+ LL_L2D(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to a native 64-bit integer.
+ */
+ operator T() const {
+ return mValue;
+ }
+
+ /**
+ * Perform unary negation on a 64-bit integer.
+ */
+ const nsTInt64 operator -(void) {
+ nsTInt64 result;
+ LL_NEG(result.mValue, mValue);
+ return result;
+ }
+
+ // Arithmetic operators
+
+ /**
+ * Increment a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator +=(const nsTInt64& aObject) {
+ LL_ADD(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Decrement a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator -=(const nsTInt64& aObject) {
+ LL_SUB(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Multiply a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator *=(const nsTInt64& aObject) {
+ LL_MUL(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Divide a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator /=(const nsTInt64& aObject) {
+ LL_DIV(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the modulus of a 64-bit integer to a 64-bit value.
+ */
+ nsTInt64& operator %=(const nsTInt64& aObject) {
+ LL_MOD(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Shift a 64-bit integer left.
+ */
+ nsTInt64& operator <<=(int aCount) {
+ LL_SHL(mValue, mValue, aCount);
+ return *this;
+ }
+
+ /**
+ * Shift a 64-bit signed integer right.
+ */
+ nsTInt64& operator >>=(int aCount) {
+ LL_SHR(mValue, mValue, aCount);
+ return *this;
+ }
+
+ // Comparison operators
+ /**
+ * Add two 64-bit integers.
+ */
+ inline const nsTInt64
+ operator +(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) += aObject2;
+ }
+
+ /**
+ * Subtract one 64-bit integer from another.
+ */
+ inline const nsTInt64
+ operator -(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) -= aObject2;
+ }
+
+ /**
+ * Multiply two 64-bit integers
+ */
+ inline const nsTInt64
+ operator *(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) *= aObject2;
+ }
+
+ /**
+ * Divide one 64-bit integer by another
+ */
+ inline const nsTInt64
+ operator /(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) /= aObject2;
+ }
+
+ /**
+ * Compute the modulus of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator %(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) %= aObject2;
+ }
+
+ /**
+ * Shift left a 64-bit integer
+ */
+ inline const nsTInt64
+ operator <<(int aCount) const {
+ return nsTInt64(*this) <<= aCount;
+ }
+
+ /**
+ * Shift right a signed 64-bit integer
+ */
+ inline const nsTInt64
+ operator >>(int aCount) const {
+ return nsTInt64(*this) >>= aCount;
+ }
+
+ /**
+ * Determine if two 64-bit integers are equal
+ */
+ inline PRBool
+ operator ==(const nsTInt64& aObject2) const {
+ return LL_EQ(mValue, aObject2.mValue);
+ }
+
+ /**
+ * Determine if two 64-bit integers are not equal
+ */
+ inline PRBool
+ operator !=(const nsTInt64& aObject2) const {
+ return LL_NE(mValue, aObject2.mValue);
+ }
+
+
+ /**
+ * Perform a bitwise AND of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator &(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) &= aObject2;
+ }
+
+ /**
+ * Perform a bitwise OR of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator |(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) |= aObject2;
+ }
+
+ /**
+ * Perform a bitwise XOR of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator ^(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) ^= aObject2;
+ }
+
+ // Bitwise operators
+
+ /**
+ * Compute the bitwise NOT of a 64-bit integer
+ */
+ const nsTInt64 operator ~(void) const {
+ nsTInt64 result;
+ LL_NOT(result.mValue, mValue);
+ return result;
+ }
+
+ /**
+ * Compute the bitwise AND with another 64-bit integer
+ */
+ nsTInt64& operator &=(const nsTInt64& aObject) {
+ LL_AND(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the bitwise OR with another 64-bit integer
+ */
+ nsTInt64& operator |=(const nsTInt64& aObject) {
+ LL_OR(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the bitwise XOR with another 64-bit integer
+ */
+ nsTInt64& operator ^=(const nsTInt64& aObject) {
+ LL_XOR(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+};
+
+typedef nsTInt64<PRInt64> nsInt64;
+typedef nsTInt64<PRUint64> nsUint64;
+
+/**
+ * Determine if one 64-bit integer is strictly greater than another, using signed values
+ */
+inline PRBool
+operator >(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return LL_CMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+inline PRBool
+operator >(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return LL_UCMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integer is greater than or equal to another, using signed values
+ */
+inline PRBool
+operator >=(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return ! LL_CMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+inline PRBool
+operator >=(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return ! LL_UCMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integer is strictly less than another, using signed values
+ */
+inline PRBool
+operator <(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return LL_CMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+inline PRBool
+operator <(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return LL_UCMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integers is less than or equal to another, using signed values
+ */
+inline PRBool
+operator <=(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return ! LL_CMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+inline PRBool
+operator <=(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return ! LL_UCMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+#endif // nsInt64_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h
new file mode 100644
index 00000000..68b06d66
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsInterfaceHashtable_h__
+#define nsInterfaceHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsCOMPtr.h"
+
+/**
+ * templated hashtable class maps keys to interface pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Interface the interface-type being wrapped
+ * @see nsDataHashtable, nsClassHashtable
+ */
+template<class KeyClass,class Interface>
+class nsInterfaceHashtable :
+ public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef Interface* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ /**
+ * Gets a weak reference to the hashtable entry.
+ * @param aFound If not nsnull, will be set to PR_TRUE if the entry is found,
+ * to PR_FALSE otherwise.
+ * @return The entry, or nsnull if not found. Do not release this pointer!
+ */
+ Interface* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
+};
+
+/**
+ * Thread-safe version of nsInterfaceHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Interface the interface-type being wrapped
+ */
+template<class KeyClass,class Interface>
+class nsInterfaceHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef Interface* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ // GetWeak does not make sense on a multi-threaded hashtable, where another
+ // thread may remove the entry (and hence release it) as soon as GetWeak
+ // returns
+};
+
+
+//
+// nsInterfaceHashtable definitions
+//
+
+template<class KeyClass,class Interface>
+PRBool
+nsInterfaceHashtable<KeyClass,Interface>::Get
+ (KeyType aKey, UserDataType* pInterface) const
+{
+ typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pInterface)
+ {
+ *pInterface = ent->mData;
+
+ NS_IF_ADDREF(*pInterface);
+ }
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pInterface to null
+ // so that it is a valid XPCOM getter
+ if (pInterface)
+ *pInterface = nsnull;
+
+ return PR_FALSE;
+}
+
+template<class KeyClass,class Interface>
+Interface*
+nsInterfaceHashtable<KeyClass,Interface>::GetWeak
+ (KeyType aKey, PRBool* aFound) const
+{
+ typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (aFound)
+ *aFound = PR_TRUE;
+
+ return ent->mData;
+ }
+
+ // Key does not exist, return nsnull and set aFound to PR_FALSE
+ if (aFound)
+ *aFound = PR_FALSE;
+ return nsnull;
+}
+
+//
+// nsInterfaceHashtableMT definitions
+//
+
+template<class KeyClass,class Interface>
+PRBool
+nsInterfaceHashtableMT<KeyClass,Interface>::Get
+ (KeyType aKey, UserDataType* pInterface) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pInterface)
+ {
+ *pInterface = ent->mData;
+
+ NS_IF_ADDREF(*pInterface);
+ }
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pInterface to null
+ // so that it is a valid XPCOM getter
+ if (pInterface)
+ *pInterface = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsInterfaceHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h b/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h
new file mode 100644
index 00000000..761c28c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsManifestLineReader_h__
+#define nsManifestLineReader_h__
+
+#include "nspr.h"
+#include "nsDebug.h"
+
+class nsManifestLineReader
+{
+public:
+ nsManifestLineReader() : mBase(nsnull) {}
+ ~nsManifestLineReader() {}
+
+ void Init(char* base, PRUint32 flen)
+ {
+ mBase = mCur = mNext = base;
+ mLength = 0;
+ mLimit = base + flen;
+ }
+
+ PRBool NextLine()
+ {
+ if(mNext >= mLimit)
+ return PR_FALSE;
+
+ mCur = mNext;
+ mLength = 0;
+
+ while(mNext < mLimit)
+ {
+ if(IsEOL(*mNext))
+ {
+ *mNext = '\0';
+ for(++mNext; mNext < mLimit; ++mNext)
+ if(!IsEOL(*mNext))
+ break;
+ return PR_TRUE;
+ }
+ ++mNext;
+ ++mLength;
+ }
+ return PR_FALSE;
+ }
+
+ int ParseLine(char** chunks, int* lengths, int maxChunks)
+ {
+ NS_ASSERTION(mCur && maxChunks && chunks, "bad call to ParseLine");
+ int found = 0;
+ chunks[found++] = mCur;
+
+ if(found < maxChunks)
+ {
+ char *lastchunk = mCur;
+ int *lastlength = lengths;
+ for(char* cur = mCur; *cur; cur++)
+ {
+ if(*cur == ',')
+ {
+ *cur = 0;
+ // always fill in the previous chunk's length
+ *lastlength++ = cur - lastchunk;
+ chunks[found++] = lastchunk = cur+1;
+ if(found == maxChunks)
+ break;
+ }
+ }
+ // crazy pointer math - calculate the length of the final chunk
+ *lastlength = (mCur + mLength) - lastchunk;
+ }
+ return found;
+ }
+
+ char* LinePtr() {return mCur;}
+ PRUint32 LineLength() {return mLength;}
+
+ PRBool IsEOL(char c) {return c == '\n' || c == '\r';}
+private:
+ char* mCur;
+ PRUint32 mLength;
+ char* mNext;
+ char* mBase;
+ char* mLimit;
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp
new file mode 100644
index 00000000..51fb04b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define NS_WEAK_OBSERVERS
+
+#include "pratom.h"
+#include "nsString.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsIWeakReference.h"
+#include "nsEnumeratorUtils.h"
+#include "nsObserverList.h"
+
+nsObserverList::nsObserverList()
+{
+ MOZ_COUNT_CTOR(nsObserverList);
+ mLock = PR_NewLock();
+}
+
+nsObserverList::~nsObserverList(void)
+{
+ MOZ_COUNT_DTOR(nsObserverList);
+ PR_DestroyLock(mLock);
+}
+
+nsresult
+nsObserverList::AddObserver(nsIObserver* anObserver, PRBool ownsWeak)
+{
+ nsresult rv;
+ PRBool inserted;
+
+ NS_ENSURE_ARG(anObserver);
+
+ nsAutoLock lock(mLock);
+
+ if (!mObserverList) {
+ rv = NS_NewISupportsArray(getter_AddRefs(mObserverList));
+ if (NS_FAILED(rv)) return rv;
+ }
+
+#ifdef NS_WEAK_OBSERVERS
+ nsCOMPtr<nsISupports> observerRef;
+ if (ownsWeak) {
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ NS_ASSERTION(weakRefFactory, "AddObserver: trying weak object that doesnt support nsIWeakReference");
+ if ( weakRefFactory )
+ observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
+ } else {
+#if DEBUG_dougt_xxx
+ // if you are hitting this assertion, contact dougt@netscape.com. There may be a ownership problem caused by his checkin to freeze nsIObserver
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ NS_ASSERTION(!weakRefFactory, "Your object supports weak references, but is being added with a strong reference");
+#endif
+ observerRef = anObserver;
+ }
+ if (!observerRef)
+ return NS_ERROR_FAILURE;
+
+ inserted = mObserverList->AppendElement(observerRef);
+#else
+ if (*anObserver)
+ inserted = mObserverList->AppendElement(*anObserver);
+#endif
+ return inserted ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsObserverList::RemoveObserver(nsIObserver* anObserver)
+{
+ PRBool removed = PR_FALSE;
+
+ NS_ENSURE_ARG(anObserver);
+
+ nsAutoLock lock(mLock);
+
+ if (!mObserverList)
+ return NS_ERROR_FAILURE;
+
+#ifdef NS_WEAK_OBSERVERS
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ nsCOMPtr<nsISupports> observerRef;
+ if (weakRefFactory) {
+ observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
+ if (observerRef)
+ removed = mObserverList->RemoveElement(observerRef);
+ if (!removed)
+ observerRef = anObserver;
+ } else
+ observerRef = anObserver;
+
+ if (!removed && observerRef)
+ removed = mObserverList->RemoveElement(observerRef);
+#else
+ if (*anObserver)
+ removed = mObserverList->RemoveElement(*anObserver);
+#endif
+ return removed ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsObserverList::GetObserverList(nsISimpleEnumerator** anEnumerator)
+{
+ nsAutoLock lock(mLock);
+
+ ObserverListEnumerator * enumerator= new ObserverListEnumerator(mObserverList);
+ *anEnumerator = enumerator;
+ if (!enumerator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(enumerator);
+ return NS_OK;
+}
+
+
+ObserverListEnumerator::ObserverListEnumerator(nsISupportsArray* aValueArray)
+ : mValueArray(aValueArray), mIndex(0)
+{
+ if (mValueArray) {
+ NS_ADDREF(mValueArray);
+ PRUint32 total;
+ mValueArray->Count(&total);
+ mIndex = PRInt32(total);
+ }
+}
+
+ObserverListEnumerator::~ObserverListEnumerator(void)
+{
+ NS_IF_RELEASE(mValueArray);
+}
+
+NS_IMPL_ISUPPORTS1(ObserverListEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+ObserverListEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ *aResult = (mIndex > 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ObserverListEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ if (mIndex <= 0 )
+ return NS_ERROR_UNEXPECTED;
+
+ mValueArray->GetElementAt(--mIndex, aResult);
+ if (*aResult) {
+ nsCOMPtr<nsIWeakReference> weakRefFactory = do_QueryInterface(*aResult);
+ if ( weakRefFactory ) {
+ nsCOMPtr<nsISupports> weakref = do_QueryReferent(weakRefFactory);
+ NS_RELEASE(*aResult);
+ NS_IF_ADDREF(*aResult = weakref);
+
+ return NS_OK;
+ }
+ }
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h
new file mode 100644
index 00000000..521ce1c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsObserverList_h___
+#define nsObserverList_h___
+
+#include "nsIObserver.h"
+#include "nsIEnumerator.h"
+#include "nsISupportsArray.h"
+#include "nsISimpleEnumerator.h"
+
+class ObserverListEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ ObserverListEnumerator(nsISupportsArray* aValueArray);
+
+private:
+ ~ObserverListEnumerator(void);
+
+protected:
+ nsISupportsArray* mValueArray;
+ PRInt32 mIndex;
+};
+
+class nsObserverList
+{
+public:
+ nsObserverList();
+ ~nsObserverList();
+
+ nsresult AddObserver(nsIObserver* anObserver, PRBool ownsWeak);
+ nsresult RemoveObserver(nsIObserver* anObserver);
+ nsresult GetObserverList(nsISimpleEnumerator** anEnumerator);
+
+protected:
+ PRLock* mLock;
+ nsCOMPtr<nsISupportsArray> mObserverList;
+};
+
+
+#endif /* nsObserverList_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp
new file mode 100644
index 00000000..f4c66bcc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prlog.h"
+#include "prlock.h"
+#include "nsIFactory.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsIObserverService.h"
+#include "nsObserverService.h"
+#include "nsObserverList.h"
+#include "nsHashtable.h"
+#include "nsIWeakReference.h"
+
+#define NS_WEAK_OBSERVERS
+
+
+
+#if defined(PR_LOGGING)
+// Log module for nsObserverService logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=ObserverService:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+PRLogModuleInfo* observerServiceLog = nsnull;
+#endif /* PR_LOGGING */
+
+////////////////////////////////////////////////////////////////////////////////
+// nsObserverService Implementation
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsObserverService, nsIObserverService)
+
+nsObserverService::nsObserverService()
+ : mObserverTopicTable(nsnull)
+{
+}
+
+nsObserverService::~nsObserverService(void)
+{
+ if(mObserverTopicTable)
+ delete mObserverTopicTable;
+}
+
+NS_METHOD
+nsObserverService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+#if defined(PR_LOGGING)
+ if (!observerServiceLog)
+ observerServiceLog = PR_NewLogModule("ObserverService");
+#endif
+
+ nsresult rv;
+ nsObserverService* os = new nsObserverService();
+ if (os == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(os);
+ rv = os->QueryInterface(aIID, aInstancePtr);
+ NS_RELEASE(os);
+ return rv;
+}
+
+static PRBool PR_CALLBACK
+ReleaseObserverList(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsObserverList* observerList = NS_STATIC_CAST(nsObserverList*, aData);
+ delete(observerList);
+ return PR_TRUE;
+}
+
+nsresult nsObserverService::GetObserverList(const char* aTopic, nsObserverList** anObserverList)
+{
+ if (anObserverList == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ if(mObserverTopicTable == nsnull)
+ {
+ mObserverTopicTable = new nsObjectHashtable(nsnull,
+ nsnull, // should never be cloned
+ ReleaseObserverList,
+ nsnull,
+ 256,
+ PR_TRUE);
+ if (mObserverTopicTable == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ nsCStringKey key(aTopic);
+
+ nsObserverList *topicObservers;
+ topicObservers = (nsObserverList *) mObserverTopicTable->Get(&key);
+
+ if (topicObservers)
+ {
+ *anObserverList = topicObservers;
+ return NS_OK;
+ }
+
+ topicObservers = new nsObserverList();
+ if (!topicObservers)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *anObserverList = topicObservers;
+ mObserverTopicTable->Put(&key, topicObservers);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsObserverService::AddObserver(nsIObserver* anObserver, const char* aTopic, PRBool ownsWeak)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anObserver == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->AddObserver(anObserver, ownsWeak);
+}
+
+NS_IMETHODIMP nsObserverService::RemoveObserver(nsIObserver* anObserver, const char* aTopic)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anObserver == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->RemoveObserver(anObserver);
+}
+
+NS_IMETHODIMP nsObserverService::EnumerateObservers(const char* aTopic, nsISimpleEnumerator** anEnumerator)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anEnumerator == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->GetObserverList(anEnumerator);
+}
+
+// Enumerate observers of aTopic and call Observe on each.
+NS_IMETHODIMP nsObserverService::NotifyObservers( nsISupports *aSubject,
+ const char *aTopic,
+ const PRUnichar *someData ) {
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsISimpleEnumerator> observers;
+ nsCOMPtr<nsISupports> observerRef;
+
+ rv = EnumerateObservers( aTopic, getter_AddRefs(observers) );
+ if ( NS_FAILED( rv ) )
+ return rv;
+ PRBool loop = PR_TRUE;
+ while( NS_SUCCEEDED(observers->HasMoreElements(&loop)) && loop)
+ {
+ observers->GetNext(getter_AddRefs(observerRef));
+ nsCOMPtr<nsIObserver> observer = do_QueryInterface(observerRef);
+ if ( observer )
+ observer->Observe( aSubject, aTopic, someData );
+#ifdef NS_WEAK_OBSERVERS
+ else
+ { // check for weak reference.
+ nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(observerRef);
+ if ( weakRef )
+ weakRef->QueryReferent(NS_GET_IID(nsIObserver), getter_AddRefs(observer));
+
+ if ( observer )
+ observer->Observe( aSubject, aTopic, someData );
+
+ PR_LOG(observerServiceLog, PR_LOG_DEBUG, ("Notification - %s\n", aTopic ? aTopic : "undefined"));
+
+ }
+#endif
+ }
+ return NS_OK;
+}
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h
new file mode 100644
index 00000000..0a08f2ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsObserverService_h___
+#define nsObserverService_h___
+
+#include "nsIObserverService.h"
+
+#define NS_OBSERVERSERVICE_CONTRACTID "@mozilla.org/observer-service;1"
+#define NS_OBSERVERSERVICE_CLASSNAME "Observer Service"
+
+class nsObserverList;
+class nsObjectHashtable;
+
+// {D07F5195-E3D1-11d2-8ACD-00105A1B8860}
+#define NS_OBSERVERSERVICE_CID \
+ { 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
+
+class nsObserverService : public nsIObserverService {
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR( NS_OBSERVERSERVICE_CID )
+
+ nsObserverService();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVERSERVICE
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsObserverService(void);
+
+ nsObjectHashtable* mObserverTopicTable;
+
+ nsresult GetObserverList(const char* aTopic, nsObserverList** anObserverList);
+
+
+};
+
+#endif /* nsObserverService_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp
new file mode 100644
index 00000000..0bdef252
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsID.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+#include "nsIInputStream.h"
+#include "nsIUnicharInputStream.h"
+#include "pratom.h"
+#include "nsEnumeratorUtils.h"
+#include "nsReadableUtils.h"
+#include "nsPrintfCString.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "nsPersistentProperties.h"
+#include "nsIProperties.h"
+#include "nsProperties.h"
+
+struct PropertyTableEntry : public PLDHashEntryHdr
+{
+ // both of these are arena-allocated
+ const char *mKey;
+ const PRUnichar *mValue;
+};
+
+static PRUnichar*
+ArenaStrdup(const nsAFlatString& aString, PLArenaPool* aArena)
+{
+ void *mem;
+ // add one to include the null terminator
+ PRInt32 len = (aString.Length()+1) * sizeof(PRUnichar);
+ PL_ARENA_ALLOCATE(mem, aArena, len);
+ NS_ASSERTION(mem, "Couldn't allocate space!\n");
+ if (mem) {
+ memcpy(mem, aString.get(), len);
+ }
+ return NS_STATIC_CAST(PRUnichar*, mem);
+}
+
+static char*
+ArenaStrdup(const nsAFlatCString& aString, PLArenaPool* aArena)
+{
+ void *mem;
+ // add one to include the null terminator
+ PRInt32 len = (aString.Length()+1) * sizeof(char);
+ PL_ARENA_ALLOCATE(mem, aArena, len);
+ NS_ASSERTION(mem, "Couldn't allocate space!\n");
+ if (mem)
+ memcpy(mem, aString.get(), len);
+ return NS_STATIC_CAST(char*, mem);
+}
+
+static const struct PLDHashTableOps property_HashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+nsPersistentProperties::nsPersistentProperties()
+: mIn(nsnull)
+{
+ mSubclass = NS_STATIC_CAST(nsIPersistentProperties*, this);
+ mTable.ops = nsnull;
+ PL_INIT_ARENA_POOL(&mArena, "PersistentPropertyArena", 2048);
+}
+
+nsPersistentProperties::~nsPersistentProperties()
+{
+ PL_FinishArenaPool(&mArena);
+ if (mTable.ops)
+ PL_DHashTableFinish(&mTable);
+}
+
+nsresult
+nsPersistentProperties::Init()
+{
+ if (!PL_DHashTableInit(&mTable, &property_HashTableOps, nsnull,
+ sizeof(PropertyTableEntry), 20)) {
+ mTable.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsPersistentProperties::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+ nsPersistentProperties* props = new nsPersistentProperties();
+ if (props == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(props);
+ nsresult rv = props->Init();
+ if (NS_SUCCEEDED(rv))
+ rv = props->QueryInterface(aIID, aResult);
+
+ NS_RELEASE(props);
+ return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsPersistentProperties, nsIPersistentProperties, nsIProperties)
+
+NS_IMETHODIMP
+nsPersistentProperties::Load(nsIInputStream *aIn)
+{
+ PRInt32 c;
+ nsresult ret = NS_NewUTF8ConverterStream(&mIn, aIn, 0);
+
+ if (ret != NS_OK) {
+ NS_WARNING("NS_NewUTF8ConverterStream failed");
+ return NS_ERROR_FAILURE;
+ }
+ c = Read();
+ while (1) {
+ c = SkipWhiteSpace(c);
+ if (c < 0) {
+ break;
+ }
+ else if ((c == '#') || (c == '!')) {
+ c = SkipLine(c);
+ continue;
+ }
+ else {
+ nsAutoString key;
+ while ((c >= 0) && (c != '=') && (c != ':')) {
+ key.Append(PRUnichar(c));
+ c = Read();
+ }
+ if (c < 0) {
+ break;
+ }
+ static const char trimThese[] = " \t";
+ key.Trim(trimThese, PR_FALSE, PR_TRUE);
+ c = Read();
+ nsAutoString value;
+ PRUint32 state = 0;
+ PRUnichar uchar = 0;
+ while ((c >= 0) && (c != '\r') && (c != '\n')) {
+ switch(state) {
+ case 0:
+ if (c == '\\') {
+ c = Read();
+ switch(c) {
+ case '\r':
+ case '\n':
+ // Only skip first EOL characters and then next line's
+ // whitespace characters. Skipping all EOL characters
+ // and all upcoming whitespace is too agressive.
+ if (c == '\r')
+ c = Read();
+ if (c == '\n')
+ c = Read();
+ while (c == ' ' || c == '\t')
+ c = Read();
+ continue;
+ case 'u':
+ case 'U':
+ state = 1;
+ uchar=0;
+ break;
+ case 't':
+ value.Append(PRUnichar('\t'));
+ break;
+ case 'n':
+ value.Append(PRUnichar('\n'));
+ break;
+ case 'r':
+ value.Append(PRUnichar('\r'));
+ break;
+ default:
+ value.Append((PRUnichar) c);
+ } // switch(c)
+ } else {
+ value.Append((PRUnichar) c);
+ }
+ c = Read();
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (('0' <= c) && (c <= '9')) {
+ uchar = (uchar << 4) | (c - '0');
+ state++;
+ c = Read();
+ } else if (('a' <= c) && (c <= 'f')) {
+ uchar = (uchar << 4) | (c - 'a' + 0x0a);
+ state++;
+ c = Read();
+ } else if (('A' <= c) && (c <= 'F')) {
+ uchar = (uchar << 4) | (c - 'A' + 0x0a);
+ state++;
+ c = Read();
+ } else {
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+ break;
+ case 5:
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+ }
+ if (state != 0) {
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+
+ value.Trim(trimThese, PR_TRUE, PR_TRUE);
+ nsAutoString oldValue;
+ mSubclass->SetStringProperty(NS_ConvertUCS2toUTF8(key), value, oldValue);
+ }
+ }
+ mIn->Close();
+ NS_RELEASE(mIn);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::SetStringProperty(const nsACString& aKey,
+ const nsAString& aNewValue,
+ nsAString& aOldValue)
+{
+#if 0
+ cout << "will add " << aKey.get() << "=" <<
+ NS_LossyConvertUCS2ToASCII(aNewValue).get() << endl;
+#endif
+
+ const nsAFlatCString& flatKey = PromiseFlatCString(aKey);
+ PropertyTableEntry *entry =
+ NS_STATIC_CAST(PropertyTableEntry*,
+ PL_DHashTableOperate(&mTable, flatKey.get(), PL_DHASH_ADD));
+
+ if (entry->mKey) {
+ aOldValue = entry->mValue;
+ NS_WARNING(nsPrintfCString(aKey.Length() + 30,
+ "the property %s already exists\n",
+ flatKey.get()).get());
+ }
+
+ entry->mKey = ArenaStrdup(flatKey, &mArena);
+ entry->mValue = ArenaStrdup(PromiseFlatString(aNewValue), &mArena);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Save(nsIOutputStream* aOut, const nsACString& aHeader)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Subclass(nsIPersistentProperties* aSubclass)
+{
+ if (aSubclass) {
+ mSubclass = aSubclass;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::GetStringProperty(const nsACString& aKey,
+ nsAString& aValue)
+{
+ const nsAFlatCString& flatKey = PromiseFlatCString(aKey);
+
+ PropertyTableEntry *entry =
+ NS_STATIC_CAST(PropertyTableEntry*,
+ PL_DHashTableOperate(&mTable, flatKey.get(), PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return NS_ERROR_FAILURE;
+
+ aValue = entry->mValue;
+ return NS_OK;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+AddElemToArray(PLDHashTable* table, PLDHashEntryHdr *hdr,
+ PRUint32 i, void *arg)
+{
+ nsISupportsArray *propArray = (nsISupportsArray *) arg;
+ PropertyTableEntry* entry =
+ NS_STATIC_CAST(PropertyTableEntry*, hdr);
+
+ nsPropertyElement *element =
+ new nsPropertyElement(nsDependentCString(entry->mKey),
+ nsDependentString(entry->mValue));
+ if (!element)
+ return PL_DHASH_STOP;
+
+ NS_ADDREF(element);
+ propArray->InsertElementAt(element, i);
+
+ return PL_DHASH_NEXT;
+}
+
+
+NS_IMETHODIMP
+nsPersistentProperties::Enumerate(nsISimpleEnumerator** aResult)
+{
+ nsCOMPtr<nsIBidirectionalEnumerator> iterator;
+
+ nsISupportsArray* propArray;
+ nsresult rv = NS_NewISupportsArray(&propArray);
+ if (rv != NS_OK)
+ return rv;
+
+ // Step through hash entries populating a transient array
+ PRUint32 n =
+ PL_DHashTableEnumerate(&mTable, AddElemToArray, (void *)propArray);
+ if (n < mTable.entryCount)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_NewArrayEnumerator(aResult, propArray);
+}
+
+
+PRInt32
+nsPersistentProperties::Read()
+{
+ PRUnichar c;
+ PRUint32 nRead;
+ nsresult ret;
+
+ ret = mIn->Read(&c, 1, &nRead);
+ if (ret == NS_OK && nRead == 1) {
+ return c;
+ }
+
+ return -1;
+}
+
+#define IS_WHITE_SPACE(c) \
+ (((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n'))
+
+PRInt32
+nsPersistentProperties::SkipWhiteSpace(PRInt32 c)
+{
+ while (IS_WHITE_SPACE(c)) {
+ c = Read();
+ }
+
+ return c;
+}
+
+PRInt32
+nsPersistentProperties::SkipLine(PRInt32 c)
+{
+ while ((c >= 0) && (c != '\r') && (c != '\n')) {
+ c = Read();
+ }
+ if (c == '\r') {
+ c = Read();
+ }
+ if (c == '\n') {
+ c = Read();
+ }
+
+ return c;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XXX Some day we'll unify the nsIPersistentProperties interface with
+// nsIProperties, but until now...
+
+NS_IMETHODIMP
+nsPersistentProperties::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Set(const char* prop, nsISupports* value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP
+nsPersistentProperties::Undefine(const char* prop)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Has(const char* prop, PRBool *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PropertyElement
+////////////////////////////////////////////////////////////////////////////////
+
+
+NS_METHOD
+nsPropertyElement::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+ nsPropertyElement* propElem = new nsPropertyElement();
+ if (propElem == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(propElem);
+ nsresult rv = propElem->QueryInterface(aIID, aResult);
+ NS_RELEASE(propElem);
+ return rv;
+}
+
+NS_IMPL_ISUPPORTS1(nsPropertyElement, nsIPropertyElement)
+
+NS_IMETHODIMP
+nsPropertyElement::GetKey(nsACString& aReturnKey)
+{
+ aReturnKey = mKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::GetValue(nsAString& aReturnValue)
+{
+ aReturnValue = mValue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::SetKey(const nsACString& aKey)
+{
+ mKey = aKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::SetValue(const nsAString& aValue)
+{
+ mValue = aValue;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h
new file mode 100644
index 00000000..020ff82d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsPersistentProperties_h___
+#define nsPersistentProperties_h___
+
+#include "nsIPersistentProperties2.h"
+#include "pldhash.h"
+#include "plarena.h"
+#include "nsString.h"
+
+class nsIUnicharInputStream;
+
+
+class nsPersistentProperties : public nsIPersistentProperties
+{
+public:
+ nsPersistentProperties();
+ nsresult Init();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROPERTIES
+ NS_DECL_NSIPERSISTENTPROPERTIES
+
+
+ // nsPersistentProperties methods:
+ PRInt32 Read();
+ PRInt32 SkipLine(PRInt32 c);
+ PRInt32 SkipWhiteSpace(PRInt32 c);
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsPersistentProperties();
+
+protected:
+ nsIUnicharInputStream* mIn;
+ PRUint32 mBufferPos;
+ PRUint32 mBufferLength;
+ nsIPersistentProperties* mSubclass;
+ struct PLDHashTable mTable;
+ PLArenaPool mArena;
+};
+
+class nsPropertyElement : public nsIPropertyElement
+{
+public:
+ nsPropertyElement()
+ {
+ }
+
+ nsPropertyElement(const nsACString& aKey, const nsAString& aValue)
+ : mKey(aKey), mValue(aValue)
+ {
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROPERTYELEMENT
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsPropertyElement() {}
+
+protected:
+ nsCString mKey;
+ nsString mValue;
+};
+
+#endif /* nsPersistentProperties_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp b/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp
new file mode 100644
index 00000000..8276e4a5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsProperties.h"
+
+//#include <iostream.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsProperties::nsProperties(nsISupports* outer)
+{
+ NS_INIT_AGGREGATED(outer);
+}
+
+NS_METHOD
+nsProperties::Create(nsISupports *outer, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
+
+ nsProperties* props = new nsProperties(outer);
+ if (props == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = props->AggregatedQueryInterface(aIID, aResult);
+ if (NS_FAILED(rv))
+ delete props;
+ return rv;
+}
+
+PRBool PR_CALLBACK
+nsProperties::ReleaseValues(nsHashKey* key, void* data, void* closure)
+{
+ nsISupports* value = (nsISupports*)data;
+ NS_IF_RELEASE(value);
+ return PR_TRUE;
+}
+
+nsProperties::~nsProperties()
+{
+ Enumerate(ReleaseValues);
+}
+
+NS_IMPL_AGGREGATED(nsProperties)
+
+NS_METHOD
+nsProperties::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+
+ if (aIID.Equals(NS_GET_IID(nsISupports)))
+ *aInstancePtr = GetInner();
+ else if (aIID.Equals(NS_GET_IID(nsIProperties)))
+ *aInstancePtr = NS_STATIC_CAST(nsIProperties*, this);
+ else {
+ *aInstancePtr = nsnull;
+ return NS_NOINTERFACE;
+ }
+
+ NS_ADDREF((nsISupports*)*aInstancePtr);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ nsresult rv;
+ nsCStringKey key(prop);
+ nsISupports* value = (nsISupports*)nsHashtable::Get(&key);
+ if (value) {
+ rv = value->QueryInterface(uuid, result);
+ }
+ else {
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsProperties::Set(const char* prop, nsISupports* value)
+{
+ nsCStringKey key(prop);
+
+ nsISupports* prevValue = (nsISupports*)Put(&key, value);
+ NS_IF_RELEASE(prevValue);
+ NS_IF_ADDREF(value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Undefine(const char* prop)
+{
+ nsCStringKey key(prop);
+ if (!Exists(&key))
+ return NS_ERROR_FAILURE;
+
+ nsISupports* prevValue = (nsISupports*)Remove(&key);
+ NS_IF_RELEASE(prevValue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Has(const char* prop, PRBool *result)
+{
+ nsCStringKey key(prop);
+ *result = nsHashtable::Exists(&key);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsProperties.h
new file mode 100644
index 00000000..ee225547
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsProperties.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsProperties_h___
+#define nsProperties_h___
+
+#include "nsIProperties.h"
+#include "nsHashtable.h"
+#include "nsAgg.h"
+
+#define NS_PROPERTIES_CID \
+{ /* 4de2bc90-b1bf-11d3-93b6-00104ba0fd40 */ \
+ 0x4de2bc90, \
+ 0xb1bf, \
+ 0x11d3, \
+ {0x93, 0xb6, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+class nsIUnicharInputStream;
+
+class nsProperties : public nsIProperties, public nsHashtable {
+public:
+
+ NS_DECL_AGGREGATED
+ NS_DECL_NSIPROPERTIES
+
+ nsProperties(nsISupports* outer);
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
+
+private:
+ ~nsProperties();
+};
+
+#endif /* nsProperties_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp
new file mode 100644
index 00000000..0a71d25d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* We need this because Solaris' version of qsort is broken and
+ * causes array bounds reads.
+ */
+
+#include <stdlib.h>
+#include "prtypes.h"
+#include "nsQuickSort.h"
+
+PR_BEGIN_EXTERN_C
+
+#if !defined(DEBUG) && (defined(__cplusplus) || defined(__gcc))
+# ifndef INLINE
+# define INLINE inline
+# endif
+#else
+# define INLINE
+#endif
+
+typedef int cmp_t(const void *, const void *, void *);
+static INLINE char *med3(char *, char *, char *, cmp_t *, void *);
+static INLINE void swapfunc(char *, char *, int, int);
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static INLINE void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc((char *)a, (char*)b, (int)es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc((char *)a, (char *)b, (int)n, swaptype)
+
+static INLINE char *
+med3(char *a, char *b, char *c, cmp_t* cmp, void *data)
+{
+ return cmp(a, b, data) < 0 ?
+ (cmp(b, c, data) < 0 ? b : (cmp(a, c, data) < 0 ? c : a ))
+ :(cmp(b, c, data) > 0 ? b : (cmp(a, c, data) < 0 ? a : c ));
+}
+
+void NS_QuickSort (
+ void *a,
+ unsigned int n,
+ unsigned int es,
+ cmp_t *cmp,
+ void *data
+ )
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, data);
+ pm = med3(pm - d, pm, pm + d, cmp, data);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, data);
+ }
+ pm = med3(pl, pm, pn, cmp, data);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a, data)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a, data)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = PR_MIN(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = PR_MIN(pd - pc, (int)(pn - pd - es));
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > (int)es)
+ NS_QuickSort(a, r / es, es, cmp, data);
+ if ((r = pd - pc) > (int)es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* NS_QuickSort(pn - r, r / es, es, cmp, data);*/
+}
+
+PR_END_EXTERN_C
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h
new file mode 100644
index 00000000..0dd16385
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* We need this because Solaris' version of qsort is broken and
+ * causes array bounds reads.
+ */
+
+#ifndef nsQuickSort_h___
+#define nsQuickSort_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_QuickSort VBoxNsxpNS_QuickSort
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**
+ * Parameters:
+ * 1. the array to sort
+ * 2. the number of elements in the array
+ * 3. the size of each array element
+ * 4. comparison function taking two elements and parameter #5 and
+ * returning an integer:
+ * + less than zero if the first element should be before the second
+ * + 0 if the order of the elements does not matter
+ * + greater than zero if the second element should be before the first
+ * 5. extra data to pass to comparison function
+ */
+PR_EXTERN(void) NS_QuickSort(void *, unsigned int, unsigned int,
+ int (*)(const void *, const void *, void *),
+ void *);
+
+PR_END_EXTERN_C
+
+#endif /* nsQuickSort_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp
new file mode 100644
index 00000000..241f795c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp
@@ -0,0 +1,443 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * nsRecyclingAllocator
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "nsRecyclingAllocator.h"
+#include "nsIMemory.h"
+#include "nsAutoLock.h"
+#include "prprf.h"
+#include "nsITimer.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+#define NS_SEC_TO_MS(s) ((s) * 1000)
+
+void
+nsRecyclingAllocator::nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure)
+{
+ nsRecyclingAllocator *obj = (nsRecyclingAllocator *) aClosure;
+ if (!obj->mTouched)
+ {
+ if (obj->mFreeList)
+ obj->FreeUnusedBuckets();
+
+ // If we are holding no more memory, there is no need for the timer.
+ // We will revive the timer on the next allocation.
+ // XXX Unfortunately there is no way to Cancel and restart the same timer.
+ // XXX So we pretty much kill it and create a new one later.
+ if (!obj->mFreeList && obj->mRecycleTimer)
+ {
+ obj->mRecycleTimer->Cancel();
+ NS_RELEASE(obj->mRecycleTimer);
+ }
+ }
+ else
+ {
+ // Clear touched so the next time the timer fires we can test whether
+ // the allocator was used or not.
+ obj->Untouch();
+ }
+}
+
+
+nsRecyclingAllocator::nsRecyclingAllocator(PRUint32 nbucket, PRUint32 recycleAfter, const char *id) :
+ mMaxBlocks(nbucket), mBlocks(nsnull), mFreeList(nsnull), mNotUsedList(nsnull),
+ mRecycleTimer(nsnull), mRecycleAfter(recycleAfter), mTouched(0), mId(id)
+#ifdef DEBUG
+ ,mNAllocated(0)
+#endif
+{
+ NS_ASSERTION(mMaxBlocks <= NS_MAX_BLOCKS, "Too many blocks. This will affect the allocator's performance.");
+
+ mLock = PR_NewLock();
+ NS_ASSERTION(mLock, "Recycling allocator cannot get lock");
+
+ Init(nbucket, recycleAfter, id);
+}
+
+nsresult
+nsRecyclingAllocator::Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id)
+{
+ nsAutoLock lock(mLock);
+
+ // Free all memory held, if any
+ while(mFreeList)
+ {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mFreeList->block);
+#else
+ free(mFreeList->block);
+#endif
+ mFreeList = mFreeList->next;
+ }
+ mFreeList = nsnull;
+
+ if (mBlocks)
+ delete [] mBlocks;
+
+ // Reinitialize everything
+ mMaxBlocks = nbucket;
+ if (nbucket)
+ {
+ // Create memory for our bookkeeping
+ mBlocks = new BlockStoreNode[mMaxBlocks];
+ if (!mBlocks)
+ return NS_ERROR_OUT_OF_MEMORY;
+ // Link them together
+ mNotUsedList = mBlocks;
+ for (PRUint32 i=0; i < mMaxBlocks-1; i++)
+ mBlocks[i].next = &(mBlocks[i+1]);
+ }
+
+ mRecycleAfter = recycleAfter;
+ mId = id;
+
+ return NS_OK;
+}
+
+nsRecyclingAllocator::~nsRecyclingAllocator()
+{
+ // Cancel and destroy recycle timer
+ if (mRecycleTimer)
+ {
+ mRecycleTimer->Cancel();
+ NS_RELEASE(mRecycleTimer);
+ }
+
+ // Free all memory held, if any
+ while(mFreeList)
+ {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mFreeList->block);
+#else
+ free(mFreeList->block);
+#endif
+ mFreeList = mFreeList->next;
+ }
+ mFreeList = nsnull;
+
+ if (mBlocks)
+ delete [] mBlocks;
+
+ if (mLock)
+ {
+ PR_DestroyLock(mLock);
+ mLock = nsnull;
+ }
+}
+
+// Allocation and free routines
+void*
+nsRecyclingAllocator::Malloc(PRSize bytes, PRBool zeroit)
+{
+ // Mark that we are using. This will prevent any
+ // timer based release of unused memory.
+ Touch();
+
+ Block* freeBlock = FindFreeBlock(bytes);
+ if (freeBlock)
+ {
+ void *data = DATA(freeBlock);
+
+ if (zeroit)
+ memset(data, 0, bytes);
+ return data;
+ }
+
+ // We need to do an allocation
+ // Add 4 bytes to what we allocate to hold the bucket index
+ PRSize allocBytes = bytes + NS_ALLOCATOR_OVERHEAD_BYTES;
+
+ // We dont have that memory already. Allocate.
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ Block *ptr = (Block *) (zeroit ? RTMemAllocZ(allocBytes) : RTMemAlloc(allocBytes));
+#else
+ Block *ptr = (Block *) (zeroit ? calloc(1, allocBytes) : malloc(allocBytes));
+#endif
+
+ // Deal with no memory situation
+ if (!ptr)
+ return ptr;
+
+ // This is the first allocation we are holding.
+ // Setup timer for releasing memory
+ // If this fails, then we wont have a timer to release unused
+ // memory. We can live with that. Also, the next allocation
+ // will try again to set the timer.
+ if (mRecycleAfter && !mRecycleTimer)
+ {
+ // known only to stuff in xpcom.
+ extern nsresult NS_NewTimer(nsITimer* *aResult, nsTimerCallbackFunc aCallback, void *aClosure,
+ PRUint32 aDelay, PRUint32 aType);
+
+ (void) NS_NewTimer(&mRecycleTimer, nsRecycleTimerCallback, this,
+ NS_SEC_TO_MS(mRecycleAfter),
+ nsITimer::TYPE_REPEATING_SLACK);
+ NS_ASSERTION(mRecycleTimer, "nsRecyclingAllocator: Creating timer failed.\n");
+ }
+
+#ifdef DEBUG
+ mNAllocated++;
+#endif
+
+ // Store size and return data portion
+ ptr->bytes = bytes;
+ return DATA(ptr);
+}
+
+void
+nsRecyclingAllocator::Free(void *ptr)
+{
+ // Mark that we are using the allocator. This will prevent any
+ // timer based release of unused memory.
+ Touch();
+
+ Block* block = DATA_TO_BLOCK(ptr);
+
+ if (!AddToFreeList(block))
+ {
+ // We are holding more than max. Failover to free
+#ifdef DEBUG_dp
+ char buf[1024];
+ // Warn if we are failing over to malloc/free and not storing it
+ // This says we have a misdesigned memory pool. The intent was
+ // once the pool was full, we would never fail over to calloc.
+ PR_snprintf(buf, sizeof(buf), "nsRecyclingAllocator(%s) FAILOVER 0x%p (%d) - %d allocations, %d max\n",
+ mId, (char *)ptr, block->bytes, mNAllocated, mMaxBlocks);
+ NS_WARNING(buf);
+ mNAllocated--;
+#endif
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(block);
+#else
+ free(block);
+#endif
+ }
+}
+
+/* FreeUnusedBuckets
+ *
+ * Frees any bucket memory that isn't in use
+ */
+
+void
+nsRecyclingAllocator::FreeUnusedBuckets()
+{
+#ifdef DEBUG_dp
+ printf("DEBUG: nsRecyclingAllocator(%s) FreeUnusedBuckets: ", mId);
+#endif
+ nsAutoLock lock(mLock);
+
+ // We will run through the freelist and free all blocks
+ BlockStoreNode* node = mFreeList;
+ while (node)
+ {
+ // Free the allocated block
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(node->block);
+#else
+ free(node->block);
+#endif
+
+#ifdef DEBUG_dp
+ printf("%d ", node->bytes);
+#endif
+ // Clear Node
+ node->block = nsnull;
+ node->bytes = 0;
+ node = node->next;
+ }
+
+ // remake the lists
+ mNotUsedList = mBlocks;
+ for (PRUint32 i=0; i < mMaxBlocks-1; i++)
+ mBlocks[i].next = &(mBlocks[i+1]);
+ mBlocks[mMaxBlocks-1].next = nsnull;
+ mFreeList = nsnull;
+
+#ifdef DEBUG
+ mNAllocated = 0;
+#endif
+#ifdef DEBUG_dp
+ printf("\n");
+#endif
+}
+
+nsRecyclingAllocator::Block*
+nsRecyclingAllocator::FindFreeBlock(PRSize bytes)
+{
+ // We dont enter lock for this check. This is intentional.
+ // Here is my logic: we are checking if (!mFreeList). Doing this check
+ // without locking can lead to unpredictable results. YES. But the effect
+ // of the unpredictedness are ok. here is why:
+ //
+ // a) if the check returned NULL when there is stuff in freelist
+ // We would just end up reallocating.
+ //
+ // b) if the check returned nonNULL when our freelist is empty
+ // This is the more likely and dangerous case. The code for
+ // FindFreeBlock() will enter lock, while (null) and return null.
+ //
+ // The reason why I chose to not enter lock for this check was that when
+ // the allocator is full, we dont want to impose any more overhead than
+ // we already are for failing over to malloc/free.
+
+ if (!mFreeList)
+ return NULL;
+
+ Block *block = nsnull;
+
+ nsAutoLock lock(mLock);
+ BlockStoreNode* freeNode = mFreeList;
+ BlockStoreNode** prevp = &mFreeList;
+
+ while (freeNode)
+ {
+ if (freeNode->bytes >= bytes)
+ {
+ // Found the best fit free block
+ block = freeNode->block;
+
+ // Clear the free node
+ freeNode->block = nsnull;
+ freeNode->bytes = 0;
+
+ // Remove free node from free list
+ *prevp = freeNode->next;
+
+ // Add removed BlockStoreNode to not used list
+ freeNode->next = mNotUsedList;
+ mNotUsedList = freeNode;
+
+ break;
+ }
+
+ prevp = &(freeNode->next);
+ freeNode = freeNode->next;
+ }
+ return block;
+}
+
+PRInt32
+nsRecyclingAllocator::AddToFreeList(Block* block)
+{
+ nsAutoLock lock(mLock);
+
+ if (!mNotUsedList)
+ return PR_FALSE;
+
+ // Pick a node from the not used list
+ BlockStoreNode *node = mNotUsedList;
+ mNotUsedList = mNotUsedList->next;
+
+ // Initialize the node
+ node->bytes = block->bytes;
+ node->block = block;
+
+ // Find the right spot in the sorted list.
+ BlockStoreNode* freeNode = mFreeList;
+ BlockStoreNode** prevp = &mFreeList;
+ while (freeNode)
+ {
+ if (freeNode->bytes >= block->bytes)
+ break;
+ prevp = &(freeNode->next);
+ freeNode = freeNode->next;
+ }
+
+ // Needs to be inserted between *prevp and freeNode
+ *prevp = node;
+ node->next = freeNode;
+
+ return PR_TRUE;
+}
+
+
+// ----------------------------------------------------------------------
+// Wrapping the recyling allocator with nsIMemory
+// ----------------------------------------------------------------------
+
+// nsIMemory methods
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsRecyclingAllocatorImpl, nsIMemory, nsIRecyclingAllocator)
+
+NS_IMETHODIMP_(void *)
+nsRecyclingAllocatorImpl::Alloc(PRSize size)
+{
+ return nsRecyclingAllocatorImpl::Malloc(size, PR_FALSE);
+}
+
+NS_IMETHODIMP_(void *)
+nsRecyclingAllocatorImpl::Realloc(void *ptr, PRSize size)
+{
+ // XXX Not yet implemented
+ return NULL;
+}
+
+NS_IMETHODIMP_(void)
+nsRecyclingAllocatorImpl::Free(void *ptr)
+{
+ nsRecyclingAllocator::Free(ptr);
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::Init(size_t nbuckets, size_t recycleAfter, const char *id)
+{
+ return nsRecyclingAllocator::Init((PRUint32) nbuckets, (PRUint32) recycleAfter, id);
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::HeapMinimize(PRBool immediate)
+{
+ // XXX Not yet implemented
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::IsLowMemory(PRBool *lowmemoryb_ptr)
+{
+ // XXX Not yet implemented
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h
new file mode 100644
index 00000000..4266b1b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h
@@ -0,0 +1,208 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * nsRecyclingAllocator
+ *
+ * This allocator is useful when we cycle through a small set of allocations
+ * repeatedly with minimal overlap. For eg. something we do for every gif
+ * file read (or) buffers required for decompression of every file from jar.
+ *
+ * What this does is keeps around the first set of memory allocated and
+ * reuses it subsequently. If all buckets are full, this falls back to
+ * malloc/free
+ *
+ * Uses a timer to release all memory allocated if not used for more than
+ * 10 secs automatically.
+ *
+ * Also there is a 4 byte maintenance overhead on every allocation.
+ *
+ * This allocator is thread safe.
+ *
+ * CAVEATS: As the number of buckets increases, this allocators performance
+ * will drop. As a general guideline, dont use this for more
+ * than NS_MAX_BLOCKS
+ */
+
+#ifndef nsRecyclingAllocator_h__
+#define nsRecyclingAllocator_h__
+
+#include "nscore.h"
+#include "pratom.h"
+#include "prlock.h"
+#include "nsIRecyclingAllocator.h"
+#include "nsIGenericFactory.h"
+
+#define NS_DEFAULT_RECYCLE_TIMEOUT 10 // secs
+#define NS_MAX_BLOCKS 24
+#define NS_ALLOCATOR_OVERHEAD_BYTES (sizeof(Block)) // bytes
+
+class nsITimer;
+class nsIMemory;
+
+class NS_COM nsRecyclingAllocator {
+ protected:
+ struct Block {
+ PRSize bytes;
+ };
+
+ // Make |BlockStoreNode| a |friend| so it can access |Block|.
+ struct BlockStoreNode;
+ friend struct BlockStoreNode;
+
+ struct BlockStoreNode {
+ BlockStoreNode() : bytes(0), block(nsnull), next(nsnull) {};
+ PRSize bytes;
+ Block *block;
+ BlockStoreNode *next;
+ };
+
+#define DATA(block) ((void *)(((char *)block) + NS_ALLOCATOR_OVERHEAD_BYTES))
+#define DATA_TO_BLOCK(data) ((Block *)((char *)(data) - NS_ALLOCATOR_OVERHEAD_BYTES))
+
+ // mMaxBlocks: Maximum number of blocks that can be allocated
+ PRUint32 mMaxBlocks;
+
+ // mBlocks:
+ // All blocks used or not.
+ BlockStoreNode *mBlocks;
+
+ // mFreeList
+ // A linked list of free blocks sorted by increasing order of size
+ BlockStoreNode* mFreeList;
+
+ // mNotUsedList
+ // A linked list of BlockStoreNodes that are not used to store
+ // any block information. When we add blocks into mFreeList, we
+ // take BlockStoreNode from here.
+ BlockStoreNode* mNotUsedList;
+
+ // mLock: Thread safety of mFreeList and mNotUsedList
+ PRLock *mLock;
+
+ // Timer for freeing unused memory
+ nsITimer *mRecycleTimer;
+
+ // mRecycleAfter:
+ // Allocator should be untouched for this many seconds for freeing
+ // unused Blocks.
+ PRUint32 mRecycleAfter;
+
+ // mTouched:
+ // says if the allocator touched any bucket. If allocator didn't touch
+ // any bucket over a time time interval, timer will call FreeUnusedBuckets()
+ PRInt32 mTouched;
+
+ // mId:
+ // a string for identifying the user of nsRecyclingAllocator
+ // User mainly for debug prints
+ const char *mId;
+
+#ifdef DEBUG
+ // mNAllocated: Number of blocks allocated
+ PRInt32 mNAllocated;
+#endif
+
+ public:
+
+ // nbucket : number of buckets to hold. Capped at NS_MAX_BUCKET
+ // recycleAfter : Try recycling allocated buckets after this many seconds
+ // id : a string used to identify debug prints. Will not be released.
+ nsRecyclingAllocator(PRUint32 nbucket = 0, PRUint32 recycleAfter = NS_DEFAULT_RECYCLE_TIMEOUT,
+ const char *id = NULL);
+ ~nsRecyclingAllocator();
+
+ nsresult Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id);
+
+ // Allocation and free routines
+ void* Malloc(PRSize size, PRBool zeroit = PR_FALSE);
+ void Free(void *ptr);
+
+ void* Calloc(PRUint32 items, PRSize size)
+ {
+ return Malloc(items * size, PR_TRUE);
+ }
+
+ // FreeUnusedBuckets - Frees any bucket memory that isn't in use
+ void FreeUnusedBuckets();
+
+ protected:
+
+ // Timer callback to trigger unused memory
+ static void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
+
+ // Freelist management
+ // FindFreeBlock: return a free block that can hold bytes (best fit)
+ Block* FindFreeBlock(PRSize bytes);
+ // AddToFreeList: adds block into our freelist for future retrieval.
+ // Returns PR_TRUE is addition was successful. PR_FALSE otherewise.
+ PRBool AddToFreeList(Block* block);
+
+ // Touch will mark that someone used this allocator
+ // Timer based release will free unused memory only if allocator
+ // was not touched for mRecycleAfter seconds.
+ void Touch() {
+ if (!mTouched)
+ PR_AtomicSet(&mTouched, 1);
+ }
+ void Untouch() {
+ PR_AtomicSet(&mTouched, 0);
+ }
+
+ friend void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
+};
+
+// ----------------------------------------------------------------------
+// Wrapping the recyling allocator with nsIMemory
+// ----------------------------------------------------------------------
+
+// Wrapping the nsRecyclingAllocator with nsIMemory
+class nsRecyclingAllocatorImpl : public nsRecyclingAllocator, public nsIRecyclingAllocator {
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORY
+ NS_DECL_NSIRECYCLINGALLOCATOR
+
+ nsRecyclingAllocatorImpl()
+ {
+ }
+
+private:
+ ~nsRecyclingAllocatorImpl() {}
+};
+#endif // nsRecyclingAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h
new file mode 100644
index 00000000..69cdbe88
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsRefPtrHashtable_h__
+#define nsRefPtrHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsAutoPtr.h"
+
+/**
+ * templated hashtable class maps keys to reference pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param RefPtr the reference-type being wrapped
+ * @see nsDataHashtable, nsClassHashtable
+ */
+template<class KeyClass, class RefPtr>
+class nsRefPtrHashtable :
+ public nsBaseHashtable< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef RefPtr* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ /**
+ * Gets a weak reference to the hashtable entry.
+ * @param aFound If not nsnull, will be set to PR_TRUE if the entry is found,
+ * to PR_FALSE otherwise.
+ * @return The entry, or nsnull if not found. Do not release this pointer!
+ */
+ RefPtr* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
+};
+
+/**
+ * Thread-safe version of nsRefPtrHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param RefPtr the reference-type being wrapped
+ */
+template<class KeyClass, class RefPtr>
+class nsRefPtrHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef RefPtr* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ // GetWeak does not make sense on a multi-threaded hashtable, where another
+ // thread may remove the entry (and hence release it) as soon as GetWeak
+ // returns
+};
+
+
+//
+// nsRefPtrHashtable definitions
+//
+
+template<class KeyClass, class RefPtr>
+PRBool
+nsRefPtrHashtable<KeyClass,RefPtr>::Get
+ (KeyType aKey, UserDataType* pRefPtr) const
+{
+ typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pRefPtr)
+ {
+ *pRefPtr = ent->mData;
+
+ NS_IF_ADDREF(*pRefPtr);
+ }
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pRefPtr to null
+ // so that it is a valid XPCOM getter
+ if (pRefPtr)
+ *pRefPtr = nsnull;
+
+ return PR_FALSE;
+}
+
+template<class KeyClass, class RefPtr>
+RefPtr*
+nsRefPtrHashtable<KeyClass,RefPtr>::GetWeak
+ (KeyType aKey, PRBool* aFound) const
+{
+ typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (aFound)
+ *aFound = PR_TRUE;
+
+ return ent->mData;
+ }
+
+ // Key does not exist, return nsnull and set aFound to PR_FALSE
+ if (aFound)
+ *aFound = PR_FALSE;
+ return nsnull;
+}
+
+//
+// nsRefPtrHashtableMT definitions
+//
+
+template<class KeyClass, class RefPtr>
+PRBool
+nsRefPtrHashtableMT<KeyClass,RefPtr>::Get
+ (KeyType aKey, UserDataType* pRefPtr) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pRefPtr)
+ {
+ *pRefPtr = ent->mData;
+
+ NS_IF_ADDREF(*pRefPtr);
+ }
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pRefPtr to null
+ // so that it is a valid XPCOM getter
+ if (pRefPtr)
+ *pRefPtr = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsRefPtrHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h b/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h
new file mode 100644
index 00000000..6c76d016
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Static Atom classes.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsStaticAtom_h__
+#define nsStaticAtom_h__
+
+#include "nsIAtom.h"
+
+// see http://www.mozilla.org/projects/xpcom/atoms.html to use this stuff
+
+// class for declaring a static list of atoms, for use with gperf
+// Keep this VERY simple
+// mString: the value of the atom - the policy is that this is only
+// ASCII, in order to avoid unnecessary conversions if
+// someone asks for this in unicode
+// mAtom: a convienience pointer - if you want to store the value of
+// the atom created by this structure somewhere, put its
+// address here
+struct nsStaticAtom {
+ const char* mString;
+ nsIAtom ** mAtom;
+};
+
+
+// register your lookup function with the atom table. Your function
+// will be called when at atom is not found in the main atom table.
+NS_COM nsresult
+NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp
new file mode 100644
index 00000000..35489c6a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Class to manage lookup of static names in a table. */
+
+#include "nsCRT.h"
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "nsStaticNameTable.h"
+
+struct NameTableEntry : public PLDHashEntryHdr
+{
+ // no ownership here!
+ const char *mKey;
+ PRInt32 mIndex;
+};
+
+PR_STATIC_CALLBACK(PRBool)
+matchNameKeysCaseInsensitive(PLDHashTable*, const PLDHashEntryHdr* aHdr,
+ const void* key)
+{
+ const NameTableEntry* entry =
+ NS_STATIC_CAST(const NameTableEntry *, aHdr);
+ const char *keyValue = NS_STATIC_CAST(const char*, key);
+
+ return (nsCRT::strcasecmp(entry->mKey, keyValue)==0);
+}
+
+/*
+ * caseInsensitiveHashKey is just like PL_DHashStringKey except it
+ * uses (*s & ~0x20) instead of simply *s. This means that "aFOO" and
+ * "afoo" and "aFoo" will all hash to the same thing. It also means
+ * that some strings that aren't case-insensensitively equal will hash
+ * to the same value, but it's just a hash function so it doesn't
+ * matter.
+ */
+PR_STATIC_CALLBACK(PLDHashNumber)
+caseInsensitiveStringHashKey(PLDHashTable *table, const void *key)
+{
+ PLDHashNumber h = 0;
+ for (const unsigned char* s =
+ NS_STATIC_CAST(const unsigned char*, key);
+ *s != '\0';
+ s++)
+ h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ (*s & ~0x20);
+ return h;
+}
+
+static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ caseInsensitiveStringHashKey,
+ matchNameKeysCaseInsensitive,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+nsStaticCaseInsensitiveNameTable::nsStaticCaseInsensitiveNameTable()
+ : mNameArray(nsnull), mNullStr("")
+{
+ MOZ_COUNT_CTOR(nsStaticCaseInsensitiveNameTable);
+ mNameTable.ops = nsnull;
+}
+
+nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
+{
+ if (mNameArray) {
+ // manually call the destructor on placement-new'ed objects
+ for (PRUint32 index = 0; index < mNameTable.entryCount; index++) {
+ mNameArray[index].~nsDependentCString();
+ }
+ nsMemory::Free((void*)mNameArray);
+ }
+ if (mNameTable.ops)
+ PL_DHashTableFinish(&mNameTable);
+ MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable);
+}
+
+PRBool
+nsStaticCaseInsensitiveNameTable::Init(const char* const aNames[], PRInt32 Count)
+{
+ NS_ASSERTION(!mNameArray, "double Init");
+ NS_ASSERTION(!mNameTable.ops, "double Init");
+ NS_ASSERTION(aNames, "null name table");
+ NS_ASSERTION(Count, "0 count");
+
+ mNameArray = (nsDependentCString*)
+ nsMemory::Alloc(Count * sizeof(nsDependentCString));
+ if (!mNameArray)
+ return PR_FALSE;
+
+ if (!PL_DHashTableInit(&mNameTable,
+ &nametable_CaseInsensitiveHashTableOps,
+ nsnull, sizeof(NameTableEntry), Count)) {
+ mNameTable.ops = nsnull;
+ return PR_FALSE;
+ }
+
+ for (PRInt32 index = 0; index < Count; ++index) {
+ const char* raw = aNames[index];
+#ifdef DEBUG
+ {
+ // verify invariants of contents
+ nsCAutoString temp1(raw);
+ nsDependentCString temp2(raw);
+ ToLowerCase(temp1);
+ NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
+ NS_ASSERTION(nsCRT::IsAscii(raw),
+ "non-ascii string in table -- "
+ "case-insensitive matching won't work right");
+ }
+#endif
+ // use placement-new to initialize the string object
+ new (&mNameArray[index]) nsDependentCString(raw);
+
+ NameTableEntry *entry =
+ NS_STATIC_CAST(NameTableEntry*,
+ PL_DHashTableOperate(&mNameTable, raw, PL_DHASH_ADD));
+
+ if (!entry) continue;
+
+ NS_ASSERTION(entry->mKey == 0, "Entry already exists!");
+
+ entry->mKey = raw; // not owned!
+ entry->mIndex = index;
+ }
+ return PR_TRUE;
+}
+
+inline PRInt32
+LookupFlatKeyword(const nsAFlatCString& aKeyword,
+ PLDHashTable& aTable)
+{
+ NameTableEntry *entry =
+ NS_STATIC_CAST(NameTableEntry*,
+ PL_DHashTableOperate(&aTable, aKeyword.get(), PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
+
+ return entry->mIndex;
+}
+
+PRInt32
+nsStaticCaseInsensitiveNameTable::Lookup(const nsACString& aName)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ return LookupFlatKeyword(PromiseFlatCString(aName), mNameTable);
+}
+
+PRInt32
+nsStaticCaseInsensitiveNameTable::Lookup(const nsAString& aName)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ nsCAutoString cstring;
+ cstring.AssignWithConversion(aName);
+ return LookupFlatKeyword(cstring, mNameTable);
+}
+
+const nsAFlatCString&
+nsStaticCaseInsensitiveNameTable::GetStringValue(PRInt32 index)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ if ((NOT_FOUND < index) && ((PRUint32)index < mNameTable.entryCount)) {
+ return mNameArray[index];
+ }
+ return mNullStr;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h
new file mode 100644
index 00000000..154a1c9d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Classes to manage lookup of static names in a table. */
+
+#ifndef nsStaticNameTable_h___
+#define nsStaticNameTable_h___
+
+#include "pldhash.h"
+/* This class supports case insensitive lookup.
+ *
+ * It differs from atom tables:
+ * - It supports case insensitive lookup.
+ * - It has minimal footprint by not copying the string table.
+ * - It does no locking.
+ * - It returns zero based indexes and const nsCString& as required by its
+ * callers in the parser.
+ * - It is not an xpcom interface - meant for fast lookup in static tables.
+ *
+ * ***REQUIREMENTS***
+ * - It *requires* that all entries in the table be lowercase only.
+ * - It *requires* that the table of strings be in memory that lives at least
+ * as long as this table object - typically a static string array.
+ */
+
+class NS_COM nsStaticCaseInsensitiveNameTable
+{
+public:
+ enum { NOT_FOUND = -1 };
+
+ PRBool Init(const char* const aNames[], PRInt32 Count);
+ PRInt32 Lookup(const nsACString& aName);
+ PRInt32 Lookup(const nsAString& aName);
+ const nsAFlatCString& GetStringValue(PRInt32 index);
+
+ nsStaticCaseInsensitiveNameTable();
+ ~nsStaticCaseInsensitiveNameTable();
+
+private:
+ nsDependentCString* mNameArray;
+ PLDHashTable mNameTable;
+ nsDependentCString mNullStr;
+};
+
+#endif /* nsStaticNameTable_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp
new file mode 100644
index 00000000..8a10b18c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsStringEnumerator.h"
+#include "prtypes.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsISimpleEnumerator.h"
+#include "nsSupportsPrimitives.h"
+
+//
+// nsStringEnumerator
+//
+
+class nsStringEnumerator : public nsIStringEnumerator,
+ public nsIUTF8StringEnumerator,
+ public nsISimpleEnumerator
+{
+public:
+ nsStringEnumerator(const nsStringArray* aArray, PRBool aOwnsArray) :
+ mArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_TRUE)
+ {}
+
+ nsStringEnumerator(const nsCStringArray* aArray, PRBool aOwnsArray) :
+ mCArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_FALSE)
+ {}
+
+ nsStringEnumerator(const nsStringArray* aArray, nsISupports* aOwner) :
+ mArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_TRUE)
+ {}
+
+ nsStringEnumerator(const nsCStringArray* aArray, nsISupports* aOwner) :
+ mCArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_FALSE)
+ {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIUTF8STRINGENUMERATOR
+
+ // have to declare nsIStringEnumerator manually, because of
+ // overlapping method names
+ NS_IMETHOD GetNext(nsAString& aResult);
+ NS_DECL_NSISIMPLEENUMERATOR
+
+private:
+ ~nsStringEnumerator() {
+ if (mOwnsArray) {
+ // const-casting is safe here, because the NS_New*
+ // constructors make sure mOwnsArray is consistent with
+ // the constness of the objects
+ if (mIsUnicode)
+ delete NS_CONST_CAST(nsStringArray*,mArray);
+ else
+ delete NS_CONST_CAST(nsCStringArray*,mCArray);
+ }
+ }
+
+ union {
+ const nsStringArray* mArray;
+ const nsCStringArray* mCArray;
+ };
+
+ inline PRUint32 Count() {
+ return mIsUnicode ? mArray->Count() : mCArray->Count();
+ }
+
+ PRUint32 mIndex;
+
+ // the owner allows us to hold a strong reference to the object
+ // that owns the array. Having a non-null value in mOwner implies
+ // that mOwnsArray is PR_FALSE, because we rely on the real owner
+ // to release the array
+ nsCOMPtr<nsISupports> mOwner;
+ PRPackedBool mOwnsArray;
+ PRPackedBool mIsUnicode;
+};
+
+NS_IMPL_ISUPPORTS3(nsStringEnumerator,
+ nsIStringEnumerator,
+ nsIUTF8StringEnumerator,
+ nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsStringEnumerator::HasMore(PRBool* aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = mIndex < Count();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::HasMoreElements(PRBool* aResult)
+{
+ return HasMore(aResult);
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsISupports** aResult)
+{
+ if (mIsUnicode) {
+ nsSupportsStringImpl* stringImpl = new nsSupportsStringImpl();
+ if (!stringImpl) return NS_ERROR_OUT_OF_MEMORY;
+
+ stringImpl->SetData(*mArray->StringAt(mIndex++));
+ *aResult = stringImpl;
+ }
+ else {
+ nsSupportsCStringImpl* cstringImpl = new nsSupportsCStringImpl();
+ if (!cstringImpl) return NS_ERROR_OUT_OF_MEMORY;
+
+ cstringImpl->SetData(*mCArray->CStringAt(mIndex++));
+ *aResult = cstringImpl;
+ }
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsAString& aResult)
+{
+ NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
+
+ if (mIsUnicode)
+ aResult = *mArray->StringAt(mIndex++);
+ else
+ CopyUTF8toUTF16(*mCArray->CStringAt(mIndex++), aResult);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsACString& aResult)
+{
+ NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
+
+ if (mIsUnicode)
+ CopyUTF16toUTF8(*mArray->StringAt(mIndex++), aResult);
+ else
+ aResult = *mCArray->CStringAt(mIndex++);
+
+ return NS_OK;
+}
+
+template<class T>
+static inline nsresult
+StringEnumeratorTail(T** aResult)
+{
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+//
+// constructors
+//
+
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray, nsISupports* aOwner)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, aOwner);
+ return StringEnumeratorTail(aResult);
+}
+
+
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray, nsISupports* aOwner)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, aOwner);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
+ nsStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_TRUE);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ nsCStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_TRUE);
+ return StringEnumeratorTail(aResult);
+}
+
+// const ones internally just forward to the non-const equivalents
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_FALSE);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_FALSE);
+ return StringEnumeratorTail(aResult);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h
new file mode 100644
index 00000000..d0080005
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIStringEnumerator.h"
+#include "nsVoidArray.h"
+
+// nsIStringEnumerator/nsIUTF8StringEnumerator implementations
+//
+// Currently all implementations support both interfaces. The
+// constructors below provide the most common interface for the given
+// type (i.e. nsIStringEnumerator for PRUnichar* strings, and so
+// forth) but any resulting enumerators can be queried to the other
+// type. Internally, the enumerators will hold onto the type that was
+// passed in and do conversion if GetNext() for the other type of
+// string is called.
+
+// There are a few different types of enumerators:
+
+//
+// These enumerators hold a pointer to the array. Be careful
+// because modifying the array may confuse the iterator, especially if
+// you insert or remove elements in the middle of the array.
+//
+
+// The non-adopting enumerator requires that the array sticks around
+// at least as long as the enumerator does. These are for constant
+// string arrays that the enumerator does not own, this could be used
+// in VERY specialized cases such as when the provider KNOWS that the
+// string enumerator will be consumed immediately, or will at least
+// outlast the array.
+// For example:
+//
+// nsCStringArray array;
+// array.AppendCString("abc");
+// array.AppendCString("def");
+// NS_NewStringEnumerator(&enumerator, &array, PR_TRUE);
+//
+// // call some internal method which iterates the enumerator
+// InternalMethod(enumerator);
+// NS_RELEASE(enumerator);
+//
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray);
+
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray);
+
+// Adopting string enumerators assume ownership of the array and will
+// call |operator delete| on the array when the enumerator is destroyed
+// this is useful when the provider creates an array soley for the
+// purpose of creating the enumerator.
+// For example:
+//
+// nsCStringArray* array = new nsCStringArray;
+// array->AppendString("abcd");
+// NS_NewAdoptingStringEnumerator(&result, array);
+NS_COM nsresult
+NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
+ nsStringArray* aArray);
+
+NS_COM nsresult
+NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ nsCStringArray* aArray);
+
+
+// these versions take a refcounted "owner" which will be addreffed
+// when the enumerator is created, and destroyed when the enumerator
+// is released. This allows providers to give non-owning pointers to
+// ns*StringArray member variables without worrying about lifetime
+// issues
+// For example:
+//
+// nsresult MyClass::Enumerate(nsIUTF8StringEnumerator** aResult) {
+// mCategoryList->AppendString("abcd");
+// return NS_NewStringEnumerator(aResult, mCategoryList, this);
+// }
+//
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray,
+ nsISupports* aOwner);
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray,
+ nsISupports* aOwner);
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp
new file mode 100644
index 00000000..e0774083
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp
@@ -0,0 +1,684 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>: |do_QueryElementAt|
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+#include "prbit.h"
+#include "nsSupportsArray.h"
+#include "nsSupportsArrayEnumerator.h"
+#include "nsAString.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+
+#if DEBUG_SUPPORTSARRAY
+#define MAXSUPPORTS 20
+
+class SupportsStats {
+public:
+ SupportsStats();
+ ~SupportsStats();
+
+};
+
+static int sizesUsed; // number of the elements of the arrays used
+static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted
+static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
+static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
+static int GrowInPlace[MAXSUPPORTS];
+
+// these are per-allocation
+static int MaxElements[3000];
+
+// very evil
+#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])++; break; } \
+ } \
+ if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
+ { sizesAlloced[sizesUsed] = (size); \
+ ((x)[sizesUsed++])++; break; \
+ } \
+ } while (0);
+
+#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])--; break; } \
+ } \
+ } while (0);
+
+
+SupportsStats::SupportsStats()
+{
+ sizesUsed = 1;
+ sizesAlloced[0] = 0;
+}
+
+SupportsStats::~SupportsStats()
+{
+ int i;
+ for (i = 0; i < sizesUsed; i++)
+ {
+ printf("Size %d:\n",sizesAlloced[i]);
+ printf("\tNumber of SupportsArrays this size (max): %d\n",NumberOfSize[i]);
+ printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
+ printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
+ }
+ printf("Max Size of SupportsArray:\n");
+ for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
+ {
+ if (MaxElements[i])
+ printf("\t%d: %d\n",i,MaxElements[i]);
+ }
+}
+
+// Just so constructor/destructor get called
+SupportsStats gSupportsStats;
+#endif
+
+nsresult
+nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const
+ {
+ nsresult status = mCollection
+ ? mCollection->QueryElementAt(mIndex, aIID, aResult)
+ : NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+
+ return status;
+ }
+
+static const PRInt32 kGrowArrayBy = 8;
+static const PRInt32 kLinearThreshold = 16 * sizeof(nsISupports *);
+
+nsSupportsArray::nsSupportsArray()
+{
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ mCount = 0;
+#if DEBUG_SUPPORTSARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0]));
+ MaxElements[0]++;
+#endif
+}
+
+nsSupportsArray::~nsSupportsArray()
+{
+ DeleteArray();
+}
+
+PRBool nsSupportsArray::GrowArrayBy(PRInt32 aGrowBy)
+{
+ // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
+ // than kLinearThreshold bytes, or a power of two if we're larger.
+ // This is much more efficient with most memory allocators, especially
+ // if it's very large, or of the allocator is binned.
+ if (aGrowBy < kGrowArrayBy)
+ aGrowBy = kGrowArrayBy;
+
+ PRUint32 newCount = mArraySize + aGrowBy; // Minimum increase
+ PRUint32 newSize = sizeof(mArray[0]) * newCount;
+
+ if (newSize >= (PRUint32) kLinearThreshold)
+ {
+ // newCount includes enough space for at least kGrowArrayBy new slots.
+ // Select the next power-of-two size in bytes above that if newSize is
+ // not a power of two.
+ if (newSize & (newSize - 1))
+ newSize = PR_BIT(PR_CeilingLog2(newSize));
+
+ newCount = newSize / sizeof(mArray[0]);
+ }
+ // XXX This would be far more efficient in many allocators if we used
+ // XXX PR_Realloc(), etc
+ nsISupports** oldArray = mArray;
+
+ mArray = new nsISupports*[newCount];
+ if (!mArray) { // ran out of memory
+ mArray = oldArray;
+ return PR_FALSE;
+ }
+ mArraySize = newCount;
+
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,mCount);
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+ if (mArraySize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0]));
+ if (oldArray != &(mAutoArray[0]))
+ SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0]));
+ mMaxSize = mArraySize;
+ }
+#endif
+ if (oldArray) { // need to move old data
+ if (0 < mCount) {
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ }
+ if (oldArray != &(mAutoArray[0])) {
+ delete[] oldArray;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+NS_METHOD
+nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return it->QueryInterface(aIID, aResult);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsSupportsArray, nsISupportsArray, nsICollection, nsISerializable)
+
+NS_IMETHODIMP
+nsSupportsArray::Read(nsIObjectInputStream *aStream)
+{
+ nsresult rv;
+
+ PRUint32 newArraySize;
+ rv = aStream->Read32(&newArraySize);
+
+ if (newArraySize <= kAutoArraySize) {
+ if (mArray != mAutoArray) {
+ delete[] mArray;
+ mArray = mAutoArray;
+ }
+ newArraySize = kAutoArraySize;
+ }
+ else {
+ if (newArraySize <= mArraySize) {
+ // Keep non-default-size mArray, it's more than big enough.
+ newArraySize = mArraySize;
+ }
+ else {
+ nsISupports** array = new nsISupports*[newArraySize];
+ if (!array)
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (mArray != mAutoArray)
+ delete[] mArray;
+ mArray = array;
+ }
+ }
+ mArraySize = newArraySize;
+
+ rv = aStream->Read32(&mCount);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!");
+ if (mCount > mArraySize)
+ mCount = mArraySize;
+
+ for (PRUint32 i = 0; i < mCount; i++) {
+ rv = aStream->ReadObject(PR_TRUE, &mArray[i]);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Write(nsIObjectOutputStream *aStream)
+{
+ nsresult rv;
+
+ rv = aStream->Write32(mArraySize);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = aStream->Write32(mCount);
+ if (NS_FAILED(rv)) return rv;
+
+ for (PRUint32 i = 0; i < mCount; i++) {
+ rv = aStream->WriteObject(mArray[i], PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return NS_OK;
+}
+
+void nsSupportsArray::DeleteArray(void)
+{
+ Clear();
+ if (mArray != &(mAutoArray[0])) {
+ delete[] mArray;
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+}
+
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::Equals(const nsISupportsArray* aOther)
+{
+ if (aOther) {
+ PRUint32 countOther;
+ nsISupportsArray* other = NS_CONST_CAST(nsISupportsArray*, aOther);
+ nsresult rv = other->Count(&countOther);
+ if (NS_FAILED( rv ))
+ return PR_FALSE;
+
+ if (mCount == countOther) {
+ PRUint32 index = mCount;
+ nsCOMPtr<nsISupports> otherElem;
+ while (index--) {
+ if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem))))
+ return PR_FALSE;
+ if (mArray[index] != otherElem)
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(nsISupports*)
+nsSupportsArray::ElementAt(PRUint32 aIndex)
+{
+ if (aIndex < mCount) {
+ nsISupports* element = mArray[aIndex];
+ NS_IF_ADDREF(element);
+ return element;
+ }
+ return 0;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
+{
+ return IndexOfStartingAt(aPossibleElement, 0);
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement,
+ PRUint32 aStartIndex)
+{
+ if (aStartIndex < mCount) {
+ const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
+ const nsISupports** ep = (start + aStartIndex);
+ const nsISupports** end = (start + mCount);
+ while (ep < end) {
+ if (aPossibleElement == *ep) {
+ return (ep - start);
+ }
+ ep++;
+ }
+ }
+ return -1;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement)
+{
+ if (0 < mCount) {
+ const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
+ const nsISupports** ep = (start + mCount);
+ while (start <= --ep) {
+ if (aPossibleElement == *ep) {
+ return (ep - start);
+ }
+ }
+ }
+ return -1;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex)
+{
+ if (aIndex <= mCount) {
+ if (mArraySize < (mCount + 1)) {
+ // need to grow the array
+ if (!GrowArrayBy(1))
+ return PR_FALSE;
+ }
+
+ // Could be slightly more efficient if GrowArrayBy knew about the
+ // split, but the difference is trivial.
+ PRUint32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
+ }
+
+ mArray[aIndex] = aElement;
+ NS_IF_ADDREF(aElement);
+ mCount++;
+
+#if DEBUG_SUPPORTSARRAY
+ if (mCount > mMaxCount &&
+ mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mCount;
+ }
+#endif
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, PRUint32 aIndex)
+{
+ if (!aElements) {
+ return PR_FALSE;
+ }
+ PRUint32 countElements;
+ if (NS_FAILED( aElements->Count( &countElements ) ))
+ return PR_FALSE;
+
+ if (aIndex <= mCount) {
+ if (mArraySize < (mCount + countElements)) {
+ // need to grow the array
+ if (!GrowArrayBy(countElements))
+ return PR_FALSE;
+ }
+
+ // Could be slightly more efficient if GrowArrayBy knew about the
+ // split, but the difference is trivial.
+ PRUint32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex + countElements, mArray + aIndex,
+ slide * sizeof(nsISupports*));
+ }
+
+ for (PRUint32 i = 0; i < countElements; ++i, ++mCount) {
+ // use GetElementAt to copy and do AddRef for us
+ if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) ))
+ return PR_FALSE;
+ }
+
+#if DEBUG_SUPPORTSARRAY
+ if (mCount > mMaxCount &&
+ mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mCount;
+ }
+#endif
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex)
+{
+ if (aIndex < mCount) {
+ NS_IF_ADDREF(aElement); // addref first in case it's the same object!
+ NS_IF_RELEASE(mArray[aIndex]);
+ mArray[aIndex] = aElement;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount)
+{
+ if (aIndex + aCount <= mCount) {
+ for (PRUint32 i = 0; i < aCount; i++)
+ NS_IF_RELEASE(mArray[aIndex+i]);
+ mCount -= aCount;
+ PRInt32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex, mArray + aIndex + aCount,
+ slide * sizeof(nsISupports*));
+ }
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex)
+{
+ PRInt32 theIndex = IndexOfStartingAt(aElement,aStartIndex);
+ if (theIndex >= 0)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveLastElement(const nsISupports* aElement)
+{
+ PRInt32 theIndex = LastIndexOf(aElement);
+ if (theIndex >= 0)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
+{
+ nsISupports *tempElement;
+
+ if (aTo == aFrom)
+ return PR_TRUE;
+
+ if (aTo < 0 || aFrom < 0 ||
+ (PRUint32) aTo >= mCount || (PRUint32) aFrom >= mCount)
+ {
+ // can't extend the array when moving an element. Also catches mImpl = null
+ return PR_FALSE;
+ }
+ tempElement = mArray[aFrom];
+
+ if (aTo < aFrom)
+ {
+ // Moving one element closer to the head; the elements inbetween move down
+ ::memmove(mArray + aTo + 1, mArray + aTo,
+ (aFrom-aTo) * sizeof(mArray[0]));
+ mArray[aTo] = tempElement;
+ }
+ else // already handled aFrom == aTo
+ {
+ // Moving one element closer to the tail; the elements inbetween move up
+ ::memmove(mArray + aFrom, mArray + aFrom + 1,
+ (aTo-aFrom) * sizeof(mArray[0]));
+ mArray[aTo] = tempElement;
+ }
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Clear(void)
+{
+ if (0 < mCount) {
+ do {
+ --mCount;
+ NS_IF_RELEASE(mArray[mCount]);
+ } while (0 != mCount);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Compact(void)
+{
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 oldArraySize = mArraySize;
+#endif
+ if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
+ nsISupports** oldArray = mArray;
+ if (mCount <= kAutoArraySize) {
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+ else {
+ mArray = new nsISupports*[mCount];
+ if (!mArray) {
+ mArray = oldArray;
+ return NS_OK;
+ }
+ mArraySize = mCount;
+ }
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray &&
+ oldArray != &(mAutoArray[0])) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,oldArraySize);
+ if (oldArray != &(mAutoArray[0]))
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+#endif
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ delete[] oldArray;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::SizeTo(PRInt32 aSize)
+{
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 oldArraySize = mArraySize;
+#endif
+ NS_ASSERTION(aSize >= 0, "negative aSize!");
+
+ // XXX for aSize < mCount we could resize to mCount
+ if (mArraySize == (PRUint32) aSize || (PRUint32) aSize < mCount)
+ return PR_TRUE; // nothing to do
+
+ // switch back to autoarray if possible
+ nsISupports** oldArray = mArray;
+ if ((PRUint32) aSize <= kAutoArraySize) {
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+ else {
+ mArray = new nsISupports*[aSize];
+ if (!mArray) {
+ mArray = oldArray;
+ return PR_FALSE;
+ }
+ mArraySize = aSize;
+ }
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray &&
+ oldArray != &(mAutoArray[0])) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,oldArraySize);
+ if (oldArray != &(mAutoArray[0]))
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+#endif
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ if (oldArray != mAutoArray)
+ delete[] oldArray;
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 aIndex = -1;
+ PRBool running = PR_TRUE;
+
+ while (running && (++aIndex < (PRInt32)mCount)) {
+ running = (*aFunc)(mArray[aIndex], aData);
+ }
+ return running;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData)
+{
+ PRUint32 aIndex = mCount;
+ PRBool running = PR_TRUE;
+
+ while (running && (0 < aIndex--)) {
+ running = (*aFunc)(mArray[aIndex], aData);
+ }
+ return running;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Enumerate(nsIEnumerator* *result)
+{
+ nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(this);
+ if (!e)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = e;
+ NS_ADDREF(e);
+ return NS_OK;
+}
+
+static PRBool
+CopyElement(nsISupports* aElement, void *aData)
+{
+ nsresult rv;
+ nsISupportsArray* newArray = (nsISupportsArray*)aData;
+ rv = newArray->AppendElement(aElement);
+ return NS_SUCCEEDED(rv);
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Clone(nsISupportsArray* *result)
+{
+ nsresult rv;
+ nsISupportsArray* newArray;
+ rv = NS_NewISupportsArray(&newArray);
+ PRBool ok = EnumerateForwards(CopyElement, newArray);
+ if (!ok) return NS_ERROR_OUT_OF_MEMORY;
+ *result = newArray;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
+{
+ nsresult rv;
+ rv = nsSupportsArray::Create(NULL, NS_GET_IID(nsISupportsArray),
+ (void**)aInstancePtrResult);
+ return rv;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h
new file mode 100644
index 00000000..0f9c9601
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsArray_h__
+#define nsSupportsArray_h__
+
+//#define DEBUG_SUPPORTSARRAY 1
+
+#include "nsISupportsArray.h"
+
+static const PRUint32 kAutoArraySize = 8;
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class NS_COM nsSupportsArray : public nsISupportsArray {
+public:
+ nsSupportsArray(void);
+ ~nsSupportsArray(void); // nonvirtual since we're not subclassed
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSISERIALIZABLE
+
+ // nsICollection methods:
+ NS_IMETHOD Count(PRUint32 *result) { *result = mCount; return NS_OK; }
+ NS_IMETHOD GetElementAt(PRUint32 aIndex, nsISupports* *result) {
+ *result = ElementAt(aIndex);
+ return NS_OK;
+ }
+ NS_IMETHOD QueryElementAt(PRUint32 aIndex, const nsIID & aIID, void * *aResult) {
+ if (aIndex < mCount) {
+ nsISupports* element = mArray[aIndex];
+ if (nsnull != element)
+ return element->QueryInterface(aIID, aResult);
+ }
+ return NS_ERROR_FAILURE;
+ }
+ NS_IMETHOD SetElementAt(PRUint32 aIndex, nsISupports* value) {
+ return ReplaceElementAt(value, aIndex) ? NS_OK : NS_ERROR_FAILURE;
+ }
+ NS_IMETHOD AppendElement(nsISupports *aElement) {
+ return InsertElementAt(aElement, mCount)/* ? NS_OK : NS_ERROR_FAILURE*/;
+ }
+ // XXX this is badly named - should be RemoveFirstElement
+ NS_IMETHOD RemoveElement(nsISupports *aElement) {
+ return RemoveElement(aElement, 0)/* ? NS_OK : NS_ERROR_FAILURE*/;
+ }
+ NS_IMETHOD_(PRBool) MoveElement(PRInt32 aFrom, PRInt32 aTo);
+ NS_IMETHOD Enumerate(nsIEnumerator* *result);
+ NS_IMETHOD Clear(void);
+
+ // nsISupportsArray methods:
+ NS_IMETHOD_(PRBool) Equals(const nsISupportsArray* aOther);
+
+ NS_IMETHOD_(nsISupports*) ElementAt(PRUint32 aIndex);
+
+ NS_IMETHOD_(PRInt32) IndexOf(const nsISupports* aPossibleElement);
+ NS_IMETHOD_(PRInt32) IndexOfStartingAt(const nsISupports* aPossibleElement,
+ PRUint32 aStartIndex = 0);
+ NS_IMETHOD_(PRInt32) LastIndexOf(const nsISupports* aPossibleElement);
+
+ NS_IMETHOD GetIndexOf(nsISupports *aPossibleElement, PRInt32 *_retval) {
+ *_retval = IndexOf(aPossibleElement);
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetIndexOfStartingAt(nsISupports *aPossibleElement,
+ PRUint32 aStartIndex, PRInt32 *_retval) {
+ *_retval = IndexOfStartingAt(aPossibleElement, aStartIndex);
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetLastIndexOf(nsISupports *aPossibleElement, PRInt32 *_retval) {
+ *_retval = LastIndexOf(aPossibleElement);
+ return NS_OK;
+ }
+
+ NS_IMETHOD_(PRBool) InsertElementAt(nsISupports* aElement, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) RemoveElementAt(PRUint32 aIndex) {
+ return RemoveElementsAt(aIndex,1);
+ }
+ NS_IMETHOD_(PRBool) RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex = 0);
+ NS_IMETHOD_(PRBool) RemoveLastElement(const nsISupports* aElement);
+
+ NS_IMETHOD DeleteLastElement(nsISupports *aElement) {
+ return (RemoveLastElement(aElement) ? NS_OK : NS_ERROR_FAILURE);
+ }
+
+ NS_IMETHOD DeleteElementAt(PRUint32 aIndex) {
+ return (RemoveElementAt(aIndex) ? NS_OK : NS_ERROR_FAILURE);
+ }
+
+ NS_IMETHOD_(PRBool) AppendElements(nsISupportsArray* aElements) {
+ return InsertElementsAt(aElements,mCount);
+ }
+
+ NS_IMETHOD Compact(void);
+
+ NS_IMETHOD_(PRBool) EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData);
+ NS_IMETHOD_(PRBool) EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData);
+
+ NS_IMETHOD Clone(nsISupportsArray **_retval);
+
+ NS_IMETHOD_(PRBool) InsertElementsAt(nsISupportsArray *aOther, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount);
+
+ NS_IMETHOD_(PRBool) SizeTo(PRInt32 aSize);
+protected:
+ void DeleteArray(void);
+
+ NS_IMETHOD_(PRBool) GrowArrayBy(PRInt32 aGrowBy);
+
+ nsISupports** mArray;
+ PRUint32 mArraySize;
+ PRUint32 mCount;
+ nsISupports* mAutoArray[kAutoArraySize];
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 mMaxCount;
+ PRUint32 mMaxSize;
+#endif
+
+private:
+ // Copy constructors are not allowed
+ nsSupportsArray(const nsISupportsArray& other);
+};
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+#endif // nsSupportsArray_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp
new file mode 100644
index 00000000..38d7d728
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSupportsArrayEnumerator.h"
+#include "nsISupportsArray.h"
+
+nsSupportsArrayEnumerator::nsSupportsArrayEnumerator(nsISupportsArray* array)
+ : mArray(array), mCursor(0)
+{
+ NS_ASSERTION(array, "null array");
+ NS_ADDREF(mArray);
+}
+
+nsSupportsArrayEnumerator::~nsSupportsArrayEnumerator()
+{
+ NS_RELEASE(mArray);
+}
+
+NS_IMPL_ISUPPORTS2(nsSupportsArrayEnumerator, nsIBidirectionalEnumerator, nsIEnumerator)
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::First()
+{
+ mCursor = 0;
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 end = (PRInt32)cnt;
+ if (mCursor < end)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Next()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 end = (PRInt32)cnt;
+ if (mCursor < end) // don't count upward forever
+ mCursor++;
+ if (mCursor < end)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::CurrentItem(nsISupports **aItem)
+{
+ NS_ASSERTION(aItem, "null out parameter");
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mCursor >= 0 && mCursor < (PRInt32)cnt) {
+ *aItem = mArray->ElementAt(mCursor);
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::IsDone()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ return (mCursor >= 0 && mCursor < (PRInt32)cnt)
+ ? NS_ENUMERATOR_FALSE : NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Last()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ mCursor = cnt - 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Prev()
+{
+ if (mCursor >= 0)
+ --mCursor;
+ if (mCursor >= 0)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_NewISupportsArrayEnumerator(nsISupportsArray* array,
+ nsIBidirectionalEnumerator* *aInstancePtrResult)
+{
+ if (aInstancePtrResult == 0)
+ return NS_ERROR_NULL_POINTER;
+ nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(array);
+ if (e == 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(e);
+ *aInstancePtrResult = e;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h
new file mode 100644
index 00000000..e987709f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsArrayEnumerator_h___
+#define nsSupportsArrayEnumerator_h___
+
+#include "nsIEnumerator.h"
+
+class nsISupportsArray;
+
+class nsSupportsArrayEnumerator : public nsIBidirectionalEnumerator {
+public:
+ NS_DECL_ISUPPORTS
+
+ nsSupportsArrayEnumerator(nsISupportsArray* array);
+
+ // nsIEnumerator methods:
+ NS_DECL_NSIENUMERATOR
+
+ // nsIBidirectionalEnumerator methods:
+ NS_DECL_NSIBIDIRECTIONALENUMERATOR
+
+private:
+ ~nsSupportsArrayEnumerator();
+
+protected:
+ nsISupportsArray* mArray;
+ PRInt32 mCursor;
+
+};
+
+#endif // __nsSupportsArrayEnumerator_h
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp
new file mode 100644
index 00000000..7fe5502a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp
@@ -0,0 +1,880 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSupportsPrimitives.h"
+#include "nsCRT.h"
+#include "nsMemory.h"
+#include "prprf.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsDependentString.h"
+#include "nsReadableUtils.h"
+#include "nsPromiseFlatString.h"
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsIDImpl, nsISupportsID, nsISupportsPrimitive)
+
+nsSupportsIDImpl::nsSupportsIDImpl()
+ : mData(nsnull)
+{
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_ID;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::GetData(nsID **aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ if(mData)
+ {
+ *aData = (nsID*) nsMemory::Clone(mData, sizeof(nsID));
+ return *aData ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aData = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::SetData(const nsID *aData)
+{
+ if(mData)
+ nsMemory::Free(mData);
+ if(aData)
+ mData = (nsID*) nsMemory::Clone(aData, sizeof(nsID));
+ else
+ mData = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::ToString(char **_retval)
+{
+ char* result;
+ NS_ASSERTION(_retval, "Bad pointer");
+ if(mData)
+ {
+ result = mData->ToString();
+ }
+ else
+ {
+ static const char nullStr[] = "null";
+ result = (char*) nsMemory::Clone(nullStr, sizeof(nullStr));
+ }
+
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/*****************************************************************************
+ * nsSupportsCStringImpl
+ *****************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsCStringImpl, nsISupportsCString,
+ nsISupportsPrimitive)
+
+NS_IMETHODIMP nsSupportsCStringImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+
+ *aType = TYPE_CSTRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::GetData(nsACString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::ToString(char **_retval)
+{
+ *_retval = ToNewCString(mData);
+
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::SetData(const nsACString& aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+/*****************************************************************************
+ * nsSupportsStringImpl
+ *****************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsStringImpl, nsISupportsString,
+ nsISupportsPrimitive)
+
+NS_IMETHODIMP nsSupportsStringImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+
+ *aType = TYPE_STRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::GetData(nsAString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::ToString(PRUnichar **_retval)
+{
+ *_retval = ToNewUnicode(mData);
+
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::SetData(const nsAString& aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsPRBoolImpl, nsISupportsPRBool,
+ nsISupportsPrimitive)
+
+nsSupportsPRBoolImpl::nsSupportsPRBoolImpl()
+ : mData(PR_FALSE)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRBOOL;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::GetData(PRBool *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::SetData(PRBool aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ const char * str = mData ? "true" : "false";
+ char* result = (char*) nsMemory::Clone(str,
+ (strlen(str)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint8Impl, nsISupportsPRUint8,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint8Impl::nsSupportsPRUint8Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT8;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::GetData(PRUint8 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::SetData(PRUint8 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%u", (PRUint16) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint16Impl, nsISupportsPRUint16,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint16Impl::nsSupportsPRUint16Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT16;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::GetData(PRUint16 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::SetData(PRUint16 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%u", (int) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint32Impl, nsISupportsPRUint32,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint32Impl::nsSupportsPRUint32Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT32;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::GetData(PRUint32 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::SetData(PRUint32 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 16;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%lu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint64Impl, nsISupportsPRUint64,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint64Impl::nsSupportsPRUint64Impl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT64;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::GetData(PRUint64 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::SetData(PRUint64 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%llu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRTimeImpl, nsISupportsPRTime,
+ nsISupportsPrimitive)
+
+nsSupportsPRTimeImpl::nsSupportsPRTimeImpl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRTIME;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::GetData(PRTime *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::SetData(PRTime aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%llu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsCharImpl, nsISupportsChar,
+ nsISupportsPrimitive)
+
+nsSupportsCharImpl::nsSupportsCharImpl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_CHAR;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::GetData(char *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::SetData(char aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::ToString(char **_retval)
+{
+ char* result;
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ if(nsnull != (result = (char*) nsMemory::Alloc(2*sizeof(char))))
+ {
+ result[0] = mData;
+ result[1] = '\0';
+ }
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt16Impl, nsISupportsPRInt16,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt16Impl::nsSupportsPRInt16Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT16;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::GetData(PRInt16 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::SetData(PRInt16 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%d", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt32Impl, nsISupportsPRInt32,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt32Impl::nsSupportsPRInt32Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT32;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::GetData(PRInt32 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::SetData(PRInt32 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 16;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%ld", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt64Impl, nsISupportsPRInt64,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt64Impl::nsSupportsPRInt64Impl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT64;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::GetData(PRInt64 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::SetData(PRInt64 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%lld", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsFloatImpl, nsISupportsFloat,
+ nsISupportsPrimitive)
+
+nsSupportsFloatImpl::nsSupportsFloatImpl()
+ : mData(float(0.0))
+{
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_FLOAT;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::GetData(float *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::SetData(float aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%f", (double) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsDoubleImpl, nsISupportsDouble,
+ nsISupportsPrimitive)
+
+nsSupportsDoubleImpl::nsSupportsDoubleImpl()
+ : mData(double(0.0))
+{
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_DOUBLE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::GetData(double *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::SetData(double aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%f", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsVoidImpl, nsISupportsVoid,
+ nsISupportsPrimitive)
+
+nsSupportsVoidImpl::nsSupportsVoidImpl()
+ : mData(nsnull)
+{
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_VOID;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::GetData(void * *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::SetData(void * aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ static const char str[] = "[raw data]";
+ char* result = (char*) nsMemory::Clone(str, sizeof(str));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsInterfacePointerImpl,
+ nsISupportsInterfacePointer,
+ nsISupportsPrimitive)
+
+nsSupportsInterfacePointerImpl::nsSupportsInterfacePointerImpl()
+ : mIID(nsnull)
+{
+}
+
+nsSupportsInterfacePointerImpl::~nsSupportsInterfacePointerImpl()
+{
+ if (mIID) {
+ nsMemory::Free(mIID);
+ }
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_INTERFACE_POINTER;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetData(nsISupports **aData)
+{
+ NS_ASSERTION(aData,"Bad pointer");
+
+ *aData = mData;
+ NS_IF_ADDREF(*aData);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::SetData(nsISupports * aData)
+{
+ mData = aData;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetDataIID(nsID **aIID)
+{
+ NS_ASSERTION(aIID,"Bad pointer");
+
+ if(mIID)
+ {
+ *aIID = (nsID*) nsMemory::Clone(mIID, sizeof(nsID));
+ return *aIID ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aIID = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::SetDataIID(const nsID *aIID)
+{
+ if(mIID)
+ nsMemory::Free(mIID);
+ if(aIID)
+ mIID = (nsID*) nsMemory::Clone(aIID, sizeof(nsID));
+ else
+ mIID = nsnull;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ static const char str[] = "[interface pointer]";
+
+ // jband sez: think about asking nsIInterfaceInfoManager whether
+ // the interface has a known human-readable name
+ char* result = (char*) nsMemory::Clone(str, sizeof(str));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsDependentCString,nsISupportsCString,nsISupportsPrimitive)
+
+nsSupportsDependentCString::nsSupportsDependentCString(const char* aStr)
+ : mData(aStr)
+{ }
+
+NS_IMETHODIMP
+nsSupportsDependentCString::GetType(PRUint16 *aType)
+{
+ NS_ENSURE_ARG_POINTER(aType);
+
+ *aType = TYPE_CSTRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::GetData(nsACString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::ToString(char **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = ToNewCString(mData);
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::SetData(const nsACString& aData)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h
new file mode 100644
index 00000000..81e83fa3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsPrimitives_h__
+#define nsSupportsPrimitives_h__
+
+#include "nsISupportsPrimitives.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+
+class nsSupportsIDImpl : public nsISupportsID
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSID
+
+ nsSupportsIDImpl();
+
+private:
+ ~nsSupportsIDImpl() { }
+
+ nsID *mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsCStringImpl : public nsISupportsCString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCSTRING
+
+ nsSupportsCStringImpl() {}
+
+private:
+ ~nsSupportsCStringImpl() {}
+
+ nsCString mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsStringImpl : public nsISupportsString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSSTRING
+
+ nsSupportsStringImpl() {}
+
+private:
+ ~nsSupportsStringImpl() {}
+
+ nsString mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRBoolImpl : public nsISupportsPRBool
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRBOOL
+
+ nsSupportsPRBoolImpl();
+
+private:
+ ~nsSupportsPRBoolImpl() {}
+
+ PRBool mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint8Impl : public nsISupportsPRUint8
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT8
+
+ nsSupportsPRUint8Impl();
+
+private:
+ ~nsSupportsPRUint8Impl() {}
+
+ PRUint8 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint16Impl : public nsISupportsPRUint16
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT16
+
+ nsSupportsPRUint16Impl();
+
+private:
+ ~nsSupportsPRUint16Impl() {}
+
+ PRUint16 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint32Impl : public nsISupportsPRUint32
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT32
+
+ nsSupportsPRUint32Impl();
+
+private:
+ ~nsSupportsPRUint32Impl() {}
+
+ PRUint32 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint64Impl : public nsISupportsPRUint64
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT64
+
+ nsSupportsPRUint64Impl();
+
+private:
+ ~nsSupportsPRUint64Impl() {}
+
+ PRUint64 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRTimeImpl : public nsISupportsPRTime
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRTIME
+
+ nsSupportsPRTimeImpl();
+
+private:
+ ~nsSupportsPRTimeImpl() {}
+
+ PRTime mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsCharImpl : public nsISupportsChar
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCHAR
+
+ nsSupportsCharImpl();
+
+private:
+ ~nsSupportsCharImpl() {}
+
+ char mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt16Impl : public nsISupportsPRInt16
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT16
+
+ nsSupportsPRInt16Impl();
+
+private:
+ ~nsSupportsPRInt16Impl() {}
+
+ PRInt16 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt32Impl : public nsISupportsPRInt32
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT32
+
+ nsSupportsPRInt32Impl();
+
+private:
+ ~nsSupportsPRInt32Impl() {}
+
+ PRInt32 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt64Impl : public nsISupportsPRInt64
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT64
+
+ nsSupportsPRInt64Impl();
+
+private:
+ ~nsSupportsPRInt64Impl() {}
+
+ PRInt64 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsFloatImpl : public nsISupportsFloat
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSFLOAT
+
+ nsSupportsFloatImpl();
+
+private:
+ ~nsSupportsFloatImpl() {}
+
+ float mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsDoubleImpl : public nsISupportsDouble
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSDOUBLE
+
+ nsSupportsDoubleImpl();
+
+private:
+ ~nsSupportsDoubleImpl() {}
+
+ double mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsVoidImpl : public nsISupportsVoid
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSVOID
+
+ nsSupportsVoidImpl();
+
+private:
+ ~nsSupportsVoidImpl() {}
+
+ void* mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsInterfacePointerImpl : public nsISupportsInterfacePointer
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSINTERFACEPOINTER
+
+ nsSupportsInterfacePointerImpl();
+
+private:
+ ~nsSupportsInterfacePointerImpl();
+
+ nsCOMPtr<nsISupports> mData;
+ nsID *mIID;
+};
+
+/***************************************************************************/
+
+/**
+ * Wraps a static const char* buffer for use with nsISupportsCString
+ *
+ * Only use this class with static buffers, or arena-allocated buffers of
+ * permanent lifetime!
+ */
+class nsSupportsDependentCString : public nsISupportsCString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCSTRING
+
+ nsSupportsDependentCString(const char* aStr);
+
+private:
+ ~nsSupportsDependentCString() {}
+
+ nsDependentCString mData;
+};
+
+#endif /* nsSupportsPrimitives_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp
new file mode 100644
index 00000000..37fa998f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
+
+PR_IMPLEMENT(PLDHashOperator)
+PL_DHashStubEnumRemove(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 ordinal,
+ void *userarg)
+{
+ return PL_DHASH_REMOVE;
+}
+
+PRUint32 nsIDHashKey::HashKey(const nsID* id)
+{
+ PRUint32 h = id->m0;
+ PRUint32 i;
+
+ h = (h>>28) ^ (h<<4) ^ id->m1;
+ h = (h>>28) ^ (h<<4) ^ id->m2;
+
+ for (i = 0; i < 8; i++)
+ h = (h>>28) ^ (h<<4) ^ id->m3[i];
+
+ return h;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h
new file mode 100644
index 00000000..1e55ada6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h
@@ -0,0 +1,429 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTHashtable_h__
+#define nsTHashtable_h__
+
+#include "nscore.h"
+#include "pldhash.h"
+#include "nsDebug.h"
+#include NEW_H
+
+// helper function for nsTHashtable::Clear()
+PR_EXTERN(PLDHashOperator) PR_CALLBACK
+PL_DHashStubEnumRemove(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 ordinal,
+ void *userArg);
+
+
+/**
+ * a base class for templated hashtables.
+ *
+ * Clients will rarely need to use this class directly. Check the derived
+ * classes first, to see if they will meet your needs.
+ *
+ * @param EntryType the templated entry-type class that is managed by the
+ * hashtable. <code>EntryType</code> must extend the following declaration,
+ * and <strong>must not declare any virtual functions or derive from classes
+ * with virtual functions.</strong> Any vtable pointer would break the
+ * PLDHashTable code.
+ *<pre> class EntryType : public PLDHashEntryHdr
+ * {
+ * public: or friend nsTHashtable<EntryType>;
+ * // KeyType is what we use when Get()ing or Put()ing this entry
+ * // this should either be a simple datatype (PRUint32, nsISupports*) or
+ * // a const reference (const nsAString&)
+ * typedef something KeyType;
+ * // KeyTypePointer is the pointer-version of KeyType, because pldhash.h
+ * // requires keys to cast to <code>const void*</code>
+ * typedef const something* KeyTypePointer;
+ *
+ * EntryType(KeyTypePointer aKey);
+ *
+ * // the copy constructor must be defined, even if AllowMemMove() == true
+ * // or you will cause link errors!
+ * EntryType(const EntryType& aEnt);
+ *
+ * // the destructor must be defined... or you will cause link errors!
+ * ~EntryType();
+ *
+ * // return the key of this entry
+ * const KeyTypePointer GetKeyPointer() const;
+ *
+ * // KeyEquals(): does this entry match this key?
+ * PRBool KeyEquals(KeyTypePointer aKey) const;
+ *
+ * // KeyToPointer(): Convert KeyType to KeyTypePointer
+ * static KeyTypePointer KeyToPointer(KeyType aKey);
+ *
+ * // HashKey(): calculate the hash number
+ * static PLDHashNumber HashKey(KeyTypePointer aKey);
+ *
+ * // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
+ * // to use the copy constructor?
+ * enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
+ * }</pre>
+ *
+ * @see nsInterfaceHashtable
+ * @see nsDataHashtable
+ * @see nsClassHashtable
+ * @author "Benjamin Smedberg <bsmedberg@covad.net>"
+ */
+
+template<class EntryType>
+class nsTHashtable
+{
+public:
+ /**
+ * A dummy constructor; you must call Init() before using this class.
+ */
+ nsTHashtable();
+
+ /**
+ * destructor, cleans up and deallocates
+ */
+ ~nsTHashtable();
+
+ /**
+ * Initialize the table. This function must be called before any other
+ * class operations. This can fail due to OOM conditions.
+ * @param initSize the initial number of buckets in the hashtable, default 16
+ * @return PR_TRUE if the class was initialized properly.
+ */
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
+
+ /**
+ * Check whether the table has been initialized. This can be useful for static hashtables.
+ * @return the initialization state of the class.
+ */
+ PRBool IsInitialized() const { return mTable.entrySize; }
+
+ /**
+ * KeyType is typedef'ed for ease of use.
+ */
+ typedef typename EntryType::KeyType KeyType;
+
+ /**
+ * KeyTypePointer is typedef'ed for ease of use.
+ */
+ typedef typename EntryType::KeyTypePointer KeyTypePointer;
+
+ /**
+ * Return the number of entries in the table.
+ * @return number of entries
+ */
+ PRUint32 Count() const { return mTable.entryCount; }
+
+ /**
+ * Get the entry associated with a key.
+ * @param aKey the key to retrieve
+ * @return pointer to the entry class, if the key exists; nsnull if the
+ * key doesn't exist
+ */
+ EntryType* GetEntry(KeyType aKey) const
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ EntryType* entry =
+ NS_REINTERPRET_CAST(EntryType*,
+ PL_DHashTableOperate(
+ NS_CONST_CAST(PLDHashTable*,&mTable),
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_LOOKUP));
+ return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
+ }
+
+ /**
+ * Get the entry associated with a key, or create a new entry,
+ * @param aKey the key to retrieve
+ * @return pointer to the entry class retreived; nsnull only if memory
+ can't be allocated
+ */
+ EntryType* PutEntry(KeyType aKey)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ return NS_STATIC_CAST(EntryType*,
+ PL_DHashTableOperate(
+ &mTable,
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_ADD));
+ }
+
+ /**
+ * Remove the entry associated with a key.
+ * @param aKey of the entry to remove
+ */
+ void RemoveEntry(KeyType aKey)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ PL_DHashTableOperate(&mTable,
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_REMOVE);
+ }
+
+ /**
+ * Remove the entry associated with a key, but don't resize the hashtable.
+ * This is a low-level method, and is not recommended unless you know what
+ * you're doing and you need the extra performance. This method can be used
+ * during enumeration, while RemoveEntry() cannot.
+ * @param aEntry the entry-pointer to remove (obtained from GetEntry or
+ * the enumerator
+ */
+ void RawRemoveEntry(EntryType* aEntry)
+ {
+ PL_DHashTableRawRemove(&mTable, aEntry);
+ }
+
+ /**
+ * client must provide an <code>Enumerator</code> function for
+ * EnumerateEntries
+ * @param aEntry the entry being enumerated
+ * @param userArg passed unchanged from <code>EnumerateEntries</code>
+ * @return combination of flags
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink ,
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink ,
+ * @link PLDHashOperator::PL_DHASH_REMOVE PL_DHASH_REMOVE @endlink
+ */
+ typedef PLDHashOperator (*PR_CALLBACK Enumerator)(EntryType* aEntry, void* userArg);
+
+ /**
+ * Enumerate all the entries of the function.
+ * @param enumFunc the <code>Enumerator</code> function to call
+ * @param userArg a pointer to pass to the
+ * <code>Enumerator</code> function
+ * @return the number of entries actually enumerated
+ */
+ PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ s_EnumArgs args = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
+ }
+
+ /**
+ * remove all entries, return hashtable to "pristine" state ;)
+ */
+ void Clear()
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
+ }
+
+protected:
+ PLDHashTable mTable;
+
+ static const void* PR_CALLBACK s_GetKey(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+ static PLDHashNumber PR_CALLBACK s_HashKey(PLDHashTable *table,
+ const void *key);
+
+ static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+ static void PR_CALLBACK s_CopyEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+ static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+ static PRBool PR_CALLBACK s_InitEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key);
+
+ /**
+ * passed internally during enumeration. Allocated on the stack.
+ *
+ * @param userFunc the Enumerator function passed to
+ * EnumerateEntries by the client
+ * @param userArg the userArg passed unaltered
+ */
+ struct s_EnumArgs
+ {
+ Enumerator userFunc;
+ void* userArg;
+ };
+
+ static PLDHashOperator PR_CALLBACK s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 number,
+ void *arg);
+private:
+ // copy constructor, not implemented
+ nsTHashtable(nsTHashtable<EntryType>& toCopy);
+
+ // assignment operator, not implemented
+ nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
+};
+
+//
+// template definitions
+//
+
+template<class EntryType>
+nsTHashtable<EntryType>::nsTHashtable()
+{
+ // entrySize is our "I'm initialized" indicator
+ mTable.entrySize = 0;
+}
+
+template<class EntryType>
+nsTHashtable<EntryType>::~nsTHashtable()
+{
+ if (mTable.entrySize)
+ PL_DHashTableFinish(&mTable);
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::Init(PRUint32 initSize)
+{
+ if (mTable.entrySize)
+ {
+ NS_ERROR("nsTHashtable::Init() should not be called twice.");
+ return PR_TRUE;
+ }
+
+ static PLDHashTableOps sOps =
+ {
+ ::PL_DHashAllocTable,
+ ::PL_DHashFreeTable,
+ s_GetKey,
+ s_HashKey,
+ s_MatchEntry,
+ ::PL_DHashMoveEntryStub,
+ s_ClearEntry,
+ ::PL_DHashFinalizeStub,
+ s_InitEntry
+ };
+
+ if (!EntryType::ALLOW_MEMMOVE)
+ {
+ sOps.moveEntry = s_CopyEntry;
+ }
+
+ if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
+ {
+ // if failed, reset "flag"
+ mTable.entrySize = 0;
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+// static definitions
+
+template<class EntryType>
+const void*
+nsTHashtable<EntryType>::s_GetKey(PLDHashTable *table,
+ PLDHashEntryHdr *entry)
+{
+ return ((EntryType*) entry)->GetKeyPointer();
+}
+
+template<class EntryType>
+PLDHashNumber
+nsTHashtable<EntryType>::s_HashKey(PLDHashTable *table,
+ const void *key)
+{
+ return EntryType::HashKey(NS_REINTERPRET_CAST(const KeyTypePointer, key));
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ return ((const EntryType*) entry)->KeyEquals(
+ NS_REINTERPRET_CAST(const KeyTypePointer, key));
+}
+
+template<class EntryType>
+void
+nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to)
+{
+ EntryType* fromEntry =
+ NS_CONST_CAST(EntryType*, NS_REINTERPRET_CAST(const EntryType*, from));
+
+ new(to) EntryType(*fromEntry);
+
+ fromEntry->~EntryType();
+}
+
+template<class EntryType>
+void
+nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry)
+{
+ NS_REINTERPRET_CAST(EntryType*,entry)->~EntryType();
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::s_InitEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key)
+{
+ new(entry) EntryType(NS_REINTERPRET_CAST(KeyTypePointer,key));
+ return PR_TRUE;
+}
+
+template<class EntryType>
+PLDHashOperator
+nsTHashtable<EntryType>::s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 number,
+ void *arg)
+{
+ // dereferences the function-pointer to the user's enumeration function
+ return (* NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userFunc)(
+ NS_REINTERPRET_CAST(EntryType*,entry),
+ NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userArg);
+}
+
+#endif // nsTHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp
new file mode 100644
index 00000000..a5f2dde0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp
@@ -0,0 +1,1557 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Portable safe sprintf code.
+ *
+ * Code based on mozilla/nsprpub/src/io/prprf.c rev 3.7
+ *
+ * Contributor(s):
+ * Kipp E.B. Hickman <kipp@netscape.com> (original author)
+ * Frank Yung-Fong Tang <ftang@netscape.com>
+ * Daniele Nicolodi <daniele@grinta.net>
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "prdtoa.h"
+#include "prlong.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "nsCRT.h"
+#include "nsTextFormatter.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/*
+** Note: on some platforms va_list is defined as an array,
+** and requires array notation.
+*/
+
+#ifdef HAVE_VA_COPY
+#define VARARGS_ASSIGN(foo, bar) VA_COPY(foo,bar)
+#elif defined(HAVE_VA_LIST_AS_ARRAY)
+#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
+#else
+#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
+#endif
+
+typedef struct SprintfStateStr SprintfState;
+
+struct SprintfStateStr {
+ int (*stuff)(SprintfState *ss, const PRUnichar *sp, PRUint32 len);
+
+ PRUnichar *base;
+ PRUnichar *cur;
+ PRUint32 maxlen;
+
+ void *stuffclosure;
+};
+
+/*
+** Numbered Arguement State
+*/
+struct NumArgState{
+ int type; /* type of the current ap */
+ va_list ap; /* point to the corresponding position on ap */
+};
+
+#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */
+
+#define TYPE_INT16 0
+#define TYPE_UINT16 1
+#define TYPE_INTN 2
+#define TYPE_UINTN 3
+#define TYPE_INT32 4
+#define TYPE_UINT32 5
+#define TYPE_INT64 6
+#define TYPE_UINT64 7
+#define TYPE_STRING 8
+#define TYPE_DOUBLE 9
+#define TYPE_INTSTR 10
+#define TYPE_UNISTRING 11
+#define TYPE_UNKNOWN 20
+
+#define _LEFT 0x1
+#define _SIGNED 0x2
+#define _SPACED 0x4
+#define _ZEROS 0x8
+#define _NEG 0x10
+
+#define ELEMENTS_OF(array_) (sizeof(array_) / sizeof(array_[0]))
+
+// Warning: if aDest isn't big enough this function returns the converted
+// string in allocated memory which must be freed using PR_FREE().
+// May return nsnull if memory couldn't be allocated.
+static PRUnichar* UTF8ToUCS2(const char *aSrc, PRUint32 aSrcLen,
+ PRUnichar* aDest, PRUint32 aDestLen)
+{
+ const char *in, *inend;
+ inend = aSrc + aSrcLen;
+ PRUnichar *out;
+ PRUint32 state;
+ PRUint32 ucs4;
+ // decide the length of the UCS2 first.
+ PRUint32 needLen = 0;
+
+ for (in = aSrc, state = 0, ucs4 = 0; in < inend; in++) {
+ if (0 == state) {
+ if (0 == (0x80 & (*in))) {
+ needLen++;
+ } else if (0xC0 == (0xE0 & (*in))) {
+ needLen++;
+ state = 1;
+ } else if (0xE0 == (0xF0 & (*in))) {
+ needLen++;
+ state = 2;
+ } else if (0xF0 == (0xF8 & (*in))) {
+ needLen+=2;
+ state = 3;
+ } else if (0xF8 == (0xFC & (*in))) {
+ needLen+=2;
+ state = 4;
+ } else if (0xFC == (0xFE & (*in))) {
+ needLen+=2;
+ state = 5;
+ } else {
+ needLen++;
+ state = 0;
+ }
+ } else {
+ NS_ASSERTION((0x80 == (0xC0 & (*in))), "The input string is not in utf8");
+ if(0x80 == (0xC0 & (*in))) {
+ state--;
+ } else {
+ state = 0;
+ }
+ }
+ }
+ needLen++; // add null termination.
+
+ // allocates sufficient memory if aDest is not big enough.
+ if (needLen > aDestLen) {
+ aDest = (PRUnichar*)PR_MALLOC(sizeof(PRUnichar) * needLen);
+ }
+ if (nsnull == aDest) {
+ return nsnull;
+ }
+ out = aDest;
+
+ for (in = aSrc, state = 0, ucs4 = 0; in < inend; in++) {
+ if (0 == state) {
+ if (0 == (0x80 & (*in))) {
+ // ASCII
+ *out++ = (PRUnichar)*in;
+ } else if (0xC0 == (0xE0 & (*in))) {
+ // 2 bytes UTF8
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 6) & 0x000007C0L;
+ state=1;
+ } else if (0xE0 == (0xF0 & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 12) & 0x0000F000L;
+ state=2;
+ } else if (0xF0 == (0xF8 & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 18) & 0x001F0000L;
+ state=3;
+ } else if (0xF8 == (0xFC & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 24) & 0x03000000L;
+ state=4;
+ } else if (0xFC == (0xFE & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 30) & 0x40000000L;
+ state=5;
+ } else {
+ NS_ASSERTION(0, "The input string is not in utf8");
+ state=0;
+ ucs4=0;
+ }
+ } else {
+ NS_ASSERTION((0x80 == (0xC0 & (*in))), "The input string is not in utf8");
+ if (0x80 == (0xC0 & (*in))) {
+ PRUint32 tmp = (*in);
+ int shift = --state * 6;
+ tmp = (tmp << shift) & (0x0000003FL << shift);
+ ucs4 |= tmp;
+ if (0 == state) {
+ if (ucs4 >= 0x00010000) {
+ if (ucs4 >= 0x00110000) {
+ *out++ = 0xFFFD;
+ } else {
+ ucs4 -= 0x00010000;
+ *out++ = 0xD800 | (0x000003FF & (ucs4 >> 10));
+ *out++ = 0xDC00 | (0x000003FF & ucs4);
+ }
+ } else {
+ *out++ = ucs4;
+ }
+ ucs4 = 0;
+ }
+ } else {
+ state = 0;
+ ucs4 = 0;
+ }
+ }
+ }
+ *out = 0x0000;
+ return aDest;
+}
+
+/*
+** Fill into the buffer using the data in src
+*/
+static int fill2(SprintfState *ss, const PRUnichar *src, int srclen,
+ int width, int flags)
+{
+ PRUnichar space = ' ';
+ int rv;
+
+ width -= srclen;
+ /* Right adjusting */
+ if ((width > 0) && ((flags & _LEFT) == 0)) {
+ if (flags & _ZEROS) {
+ space = '0';
+ }
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Copy out the source data */
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ /* Left adjusting */
+ if ((width > 0) && ((flags & _LEFT) != 0)) {
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Fill a number. The order is: optional-sign zero-filling conversion-digits
+*/
+static int fill_n(SprintfState *ss, const PRUnichar *src, int srclen,
+ int width, int prec, int type, int flags)
+{
+ int zerowidth = 0;
+ int precwidth = 0;
+ int signwidth = 0;
+ int leftspaces = 0;
+ int rightspaces = 0;
+ int cvtwidth;
+ int rv;
+ PRUnichar sign;
+ PRUnichar space = ' ';
+ PRUnichar zero = '0';
+
+ if ((type & 1) == 0) {
+ if (flags & _NEG) {
+ sign = '-';
+ signwidth = 1;
+ } else if (flags & _SIGNED) {
+ sign = '+';
+ signwidth = 1;
+ } else if (flags & _SPACED) {
+ sign = ' ';
+ signwidth = 1;
+ }
+ }
+ cvtwidth = signwidth + srclen;
+
+ if (prec > 0) {
+ if (prec > srclen) {
+ /* Need zero filling */
+ precwidth = prec - srclen;
+ cvtwidth += precwidth;
+ }
+ }
+
+ if ((flags & _ZEROS) && (prec < 0)) {
+ if (width > cvtwidth) {
+ /* Zero filling */
+ zerowidth = width - cvtwidth;
+ cvtwidth += zerowidth;
+ }
+ }
+
+ if (flags & _LEFT) {
+ if (width > cvtwidth) {
+ /* Space filling on the right (i.e. left adjusting) */
+ rightspaces = width - cvtwidth;
+ }
+ } else {
+ if (width > cvtwidth) {
+ /* Space filling on the left (i.e. right adjusting) */
+ leftspaces = width - cvtwidth;
+ }
+ }
+ while (--leftspaces >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ if (signwidth) {
+ rv = (*ss->stuff)(ss, &sign, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--precwidth >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--zerowidth >= 0) {
+ rv = (*ss->stuff)(ss, &zero, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+ while (--rightspaces >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+** Convert a long into its printable form
+*/
+static int cvt_l(SprintfState *ss, long num, int width, int prec,
+ int radix, int type, int flags, const PRUnichar *hexp)
+{
+ PRUnichar cvtbuf[100];
+ PRUnichar *cvt;
+ int digits;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (num == 0)) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
+ digits = 0;
+ while (num) {
+ int digit = (((unsigned long)num) % radix) & 0xF;
+ *--cvt = hexp[digit];
+ digits++;
+ num = (long)(((unsigned long)num) / radix);
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a 64-bit integer into its printable form
+*/
+static int cvt_ll(SprintfState *ss, PRInt64 num, int width, int prec,
+ int radix, int type, int flags, const PRUnichar *hexp)
+{
+ PRUnichar cvtbuf[100];
+ PRUnichar *cvt;
+ int digits;
+ PRInt64 rad;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (LL_IS_ZERO(num))) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ LL_I2L(rad, radix);
+ cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
+ digits = 0;
+ while (!LL_IS_ZERO(num)) {
+ PRInt32 digit;
+ PRInt64 quot, rem;
+ LL_UDIVMOD(&quot, &rem, num, rad);
+ LL_L2I(digit, rem);
+ *--cvt = hexp[digit & 0xf];
+ digits++;
+ num = quot;
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a double precision floating point number into its printable
+** form.
+*/
+static int cvt_f(SprintfState *ss, double d, int width, int prec,
+ const PRUnichar type, int flags)
+{
+ int mode = 2;
+ int decpt;
+ int sign;
+ char buf[256];
+ char * bufp = buf;
+ int bufsz = 256;
+ char num[256];
+ char * nump;
+ char * endnum;
+ int numdigits = 0;
+ char exp = 'e';
+
+ if (prec == -1) {
+ prec = 6;
+ } else if (prec > 50) {
+ // limit precision to avoid PR_dtoa bug 108335
+ // and to prevent buffers overflows
+ prec = 50;
+ }
+
+ switch (type) {
+ case 'f':
+ numdigits = prec;
+ mode = 3;
+ break;
+ case 'E':
+ exp = 'E';
+ // no break
+ case 'e':
+ numdigits = prec + 1;
+ mode = 2;
+ break;
+ case 'G':
+ exp = 'E';
+ // no break
+ case 'g':
+ if (prec == 0) {
+ prec = 1;
+ }
+ numdigits = prec;
+ mode = 2;
+ break;
+ default:
+ NS_ERROR("invalid type passed to cvt_f");
+ }
+
+ if (PR_dtoa(d, mode, numdigits, &decpt, &sign, &endnum, num, bufsz) == PR_FAILURE) {
+ buf[0] = '\0';
+ return -1;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ if (sign) {
+ *bufp++ = '-';
+ } else if (flags & _SIGNED) {
+ *bufp++ = '+';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++)) { }
+ } else {
+
+ switch (type) {
+
+ case 'E':
+ case 'e':
+
+ *bufp++ = *nump++;
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ prec--;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ *bufp++ = exp;
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
+ break;
+
+ case 'f':
+
+ if (decpt < 1) {
+ *bufp++ = '0';
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (decpt++ && prec-- > 0) {
+ *bufp++ = '0';
+ }
+ while (*nump && prec-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ } else {
+ while (*nump && decpt-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (decpt-- > 0) {
+ *bufp++ = '0';
+ }
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (*nump && prec-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ }
+ *bufp = '\0';
+ break;
+
+ case 'G':
+ case 'g':
+
+ if ((decpt < -3) || ((decpt - 1) >= prec)) {
+ *bufp++ = *nump++;
+ numdigits--;
+ if (numdigits > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = exp;
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
+ } else {
+ if (decpt < 1) {
+ *bufp++ = '0';
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ } else {
+ while (*nump && decpt-- > 0) {
+ *bufp++ = *nump++;
+ numdigits--;
+ }
+ while (decpt-- > 0) {
+ *bufp++ = '0';
+ }
+ if (numdigits > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ }
+ *bufp = '\0';
+ }
+ }
+ }
+
+ PRUnichar rbuf[256];
+ PRUnichar *rbufp = rbuf;
+ bufp = buf;
+ // cast to PRUnichar
+ while ((*rbufp++ = *bufp++)) { }
+ *rbufp = '\0';
+
+ return fill2(ss, rbuf, nsCRT::strlen(rbuf), width, flags);
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_S(SprintfState *ss, const PRUnichar *s, int width,
+ int prec, int flags)
+{
+ int slen;
+
+ if (prec == 0) {
+ return 0;
+ }
+
+ /* Limit string length by precision value */
+ slen = s ? nsCRT::strlen(s) : 6;
+ if (prec > 0) {
+ if (prec < slen) {
+ slen = prec;
+ }
+ }
+
+ /* and away we go */
+ NS_NAMED_LITERAL_STRING(nullstr, "(null)");
+
+ return fill2(ss, s ? s : nullstr.get(), slen, width, flags);
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_s(SprintfState *ss, const char *s, int width,
+ int prec, int flags)
+{
+ // convert s from UTF8 to PRUnichar*
+ // Fix me !!!
+ PRUnichar buf[256];
+ PRUnichar *retbuf = nsnull;
+
+ if (s) {
+ retbuf = UTF8ToUCS2(s, strlen(s), buf, 256);
+ if(nsnull == retbuf) {
+ return -1;
+ }
+ }
+ int ret = cvt_S(ss, retbuf, width, prec, flags);
+
+ if (retbuf != buf) {
+ PR_DELETE(retbuf);
+ }
+ return ret;
+}
+
+/*
+** BiuldArgArray stands for Numbered Argument list Sprintf
+** for example,
+** fmp = "%4$i, %2$d, %3s, %1d";
+** the number must start from 1, and no gap among them
+*/
+
+static struct NumArgState* BuildArgArray(const PRUnichar *fmt,
+ va_list ap, int * rv,
+ struct NumArgState * nasArray)
+{
+ int number = 0, cn = 0, i;
+ const PRUnichar* p;
+ PRUnichar c;
+ struct NumArgState* nas;
+
+ /*
+ ** first pass:
+ ** detemine how many legal % I have got, then allocate space
+ */
+ p = fmt;
+ *rv = 0;
+ i = 0;
+ while ((c = *p++) != 0) {
+ if (c != '%') {
+ continue;
+ }
+ /* skip %% case */
+ if ((c = *p++) == '%') {
+ continue;
+ }
+
+ while( c != 0 ){
+ if (c > '9' || c < '0') {
+ /* numbered argument csae */
+ if (c == '$') {
+ if (i > 0) {
+ *rv = -1;
+ return NULL;
+ }
+ number++;
+ break;
+
+ } else {
+ /* non-numbered argument case */
+ if (number > 0) {
+ *rv = -1;
+ return NULL;
+ }
+ i = 1;
+ break;
+ }
+ }
+ c = *p++;
+ }
+ }
+
+ if (number == 0) {
+ return NULL;
+ }
+
+ if (number > NAS_DEFAULT_NUM) {
+ nas = (struct NumArgState*)PR_MALLOC(number * sizeof(struct NumArgState));
+ if (!nas) {
+ *rv = -1;
+ return NULL;
+ }
+ } else {
+ nas = nasArray;
+ }
+
+ for (i = 0; i < number; i++) {
+ nas[i].type = TYPE_UNKNOWN;
+ }
+
+ /*
+ ** second pass:
+ ** set nas[].type
+ */
+ p = fmt;
+ while ((c = *p++) != 0) {
+ if (c != '%') {
+ continue;
+ }
+ c = *p++;
+ if (c == '%') {
+ continue;
+ }
+ cn = 0;
+ /* should imporve error check later */
+ while (c && c != '$') {
+ cn = cn*10 + c - '0';
+ c = *p++;
+ }
+
+ if (!c || cn < 1 || cn > number) {
+ *rv = -1;
+ break;
+ }
+
+ /* nas[cn] starts from 0, and make sure
+ nas[cn].type is not assigned */
+ cn--;
+ if (nas[cn].type != TYPE_UNKNOWN) {
+ continue;
+ }
+
+ c = *p++;
+
+ /* width */
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ } else {
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+
+ /* precision */
+ if (c == '.') {
+ c = *p++;
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ } else {
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+ }
+
+ /* size */
+ nas[cn].type = TYPE_INTN;
+ if (c == 'h') {
+ nas[cn].type = TYPE_INT16;
+ c = *p++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ } else if (c == 'l') {
+ nas[cn].type = TYPE_INT32;
+ c = *p++;
+ if (c == 'l') {
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ }
+ }
+
+ /* format */
+ switch (c) {
+ case 'd':
+ case 'c':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ nas[cn].type = TYPE_DOUBLE;
+ break;
+
+ case 'p':
+ /* XXX should use cpp */
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ nas[cn].type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ nas[cn].type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(PRIntn)) {
+ nas[cn].type = TYPE_UINTN;
+ } else {
+ nas[cn].type = TYPE_UNKNOWN;
+ }
+ break;
+
+ case 'C':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ nas[cn].type = TYPE_UNKNOWN;
+ break;
+
+ case 'S':
+ nas[cn].type = TYPE_UNISTRING;
+ break;
+
+ case 's':
+ nas[cn].type = TYPE_STRING;
+ break;
+
+ case 'n':
+ nas[cn].type = TYPE_INTSTR;
+ break;
+
+ default:
+ PR_ASSERT(0);
+ nas[cn].type = TYPE_UNKNOWN;
+ break;
+ }
+
+ /* get a legal para. */
+ if (nas[cn].type == TYPE_UNKNOWN) {
+ *rv = -1;
+ break;
+ }
+ }
+
+
+ /*
+ ** third pass
+ ** fill the nas[cn].ap
+ */
+ if (*rv < 0) {
+ if( nas != nasArray ) {
+ PR_DELETE(nas);
+ }
+ return NULL;
+ }
+
+ cn = 0;
+ while (cn < number) {
+ if (nas[cn].type == TYPE_UNKNOWN) {
+ cn++;
+ continue;
+ }
+
+ VARARGS_ASSIGN(nas[cn].ap, ap);
+
+ switch (nas[cn].type) {
+ case TYPE_INT16:
+ case TYPE_UINT16:
+ case TYPE_INTN:
+ case TYPE_UINTN: (void)va_arg(ap, PRIntn); break;
+
+ case TYPE_INT32: (void)va_arg(ap, PRInt32); break;
+
+ case TYPE_UINT32: (void)va_arg(ap, PRUint32); break;
+
+ case TYPE_INT64: (void)va_arg(ap, PRInt64); break;
+
+ case TYPE_UINT64: (void)va_arg(ap, PRUint64); break;
+
+ case TYPE_STRING: (void)va_arg(ap, char*); break;
+
+ case TYPE_INTSTR: (void)va_arg(ap, PRIntn*); break;
+
+ case TYPE_DOUBLE: (void)va_arg(ap, double); break;
+
+ case TYPE_UNISTRING: (void)va_arg(ap, PRUnichar*); break;
+
+ default:
+ if( nas != nasArray ) {
+ PR_DELETE( nas );
+ }
+ *rv = -1;
+ return NULL;
+ }
+ cn++;
+ }
+ return nas;
+}
+
+/*
+** The workhorse sprintf code.
+*/
+static int dosprintf(SprintfState *ss, const PRUnichar *fmt, va_list ap)
+{
+ PRUnichar c;
+ int flags, width, prec, radix, type;
+ union {
+ PRUnichar ch;
+ int i;
+ long l;
+ PRInt64 ll;
+ double d;
+ const char *s;
+ const PRUnichar *S;
+ int *ip;
+ } u;
+ PRUnichar space = ' ';
+ const PRUnichar *fmt0;
+
+ nsAutoString hex;
+ hex.AssignLiteral("0123456789abcdef");
+
+ nsAutoString HEX;
+ HEX.AssignLiteral("0123456789ABCDEF");
+
+ const PRUnichar *hexp;
+ int rv, i;
+ struct NumArgState* nas = NULL;
+ struct NumArgState nasArray[NAS_DEFAULT_NUM];
+ /* in "%4$.2f" dolPt will point to . */
+ const PRUnichar* dolPt = NULL;
+
+
+ /*
+ ** build an argument array, IF the fmt is numbered argument
+ ** list style, to contain the Numbered Argument list pointers
+ */
+ nas = BuildArgArray (fmt, ap, &rv, nasArray);
+ if (rv < 0) {
+ /* the fmt contains error Numbered Argument format, jliu@netscape.com */
+ PR_ASSERT(0);
+ return rv;
+ }
+
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+ fmt0 = fmt - 1;
+
+ /*
+ ** Gobble up the % format string. Hopefully we have handled all
+ ** of the strange cases!
+ */
+ flags = 0;
+ c = *fmt++;
+ if (c == '%') {
+ /* quoting a % with %% */
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ if (nas != NULL) {
+ /* the fmt contains the Numbered Arguments feature */
+ i = 0;
+ /* should imporve error check later */
+ while (c && c != '$') {
+ i = (i * 10) + (c - '0');
+ c = *fmt++;
+ }
+
+ if (nas[i-1].type == TYPE_UNKNOWN) {
+ if (nas && (nas != nasArray)) {
+ PR_DELETE(nas);
+ }
+ return -1;
+ }
+
+ ap = nas[i-1].ap;
+ dolPt = fmt;
+ c = *fmt++;
+ }
+
+ /*
+ * Examine optional flags. Note that we do not implement the
+ * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is
+ * somewhat ambiguous and not ideal, which is perhaps why
+ * the various sprintf() implementations are inconsistent
+ * on this feature.
+ */
+ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
+ if (c == '-') flags |= _LEFT;
+ if (c == '+') flags |= _SIGNED;
+ if (c == ' ') flags |= _SPACED;
+ if (c == '0') flags |= _ZEROS;
+ c = *fmt++;
+ }
+ if (flags & _SIGNED) flags &= ~_SPACED;
+ if (flags & _LEFT) flags &= ~_ZEROS;
+
+ /* width */
+ if (c == '*') {
+ c = *fmt++;
+ width = va_arg(ap, int);
+ } else {
+ width = 0;
+ while ((c >= '0') && (c <= '9')) {
+ width = (width * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+
+ /* precision */
+ prec = -1;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == '*') {
+ c = *fmt++;
+ prec = va_arg(ap, int);
+ } else {
+ prec = 0;
+ while ((c >= '0') && (c <= '9')) {
+ prec = (prec * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+ }
+
+ /* size */
+ type = TYPE_INTN;
+ if (c == 'h') {
+ type = TYPE_INT16;
+ c = *fmt++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ type = TYPE_INT64;
+ c = *fmt++;
+ } else if (c == 'l') {
+ type = TYPE_INT32;
+ c = *fmt++;
+ if (c == 'l') {
+ type = TYPE_INT64;
+ c = *fmt++;
+ }
+ }
+
+ /* format */
+ hexp = hex.get();
+ switch (c) {
+ case 'd':
+ case 'i': /* decimal/integer */
+ radix = 10;
+ goto fetch_and_convert;
+
+ case 'o': /* octal */
+ radix = 8;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'u': /* unsigned decimal */
+ radix = 10;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'x': /* unsigned hex */
+ radix = 16;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'X': /* unsigned HEX */
+ radix = 16;
+ hexp = HEX.get();
+ type |= 1;
+ goto fetch_and_convert;
+
+ fetch_and_convert:
+ switch (type) {
+ case TYPE_INT16:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINT16:
+ u.l = va_arg(ap, int) & 0xffff;
+ goto do_long;
+ case TYPE_INTN:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINTN:
+ u.l = (long)va_arg(ap, unsigned int);
+ goto do_long;
+
+ case TYPE_INT32:
+ u.l = va_arg(ap, PRInt32);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINT32:
+ u.l = (long)va_arg(ap, PRUint32);
+ do_long:
+ rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case TYPE_INT64:
+ u.ll = va_arg(ap, PRInt64);
+ if (!LL_GE_ZERO(u.ll)) {
+ LL_NEG(u.ll, u.ll);
+ flags |= _NEG;
+ }
+ goto do_longlong;
+ case TYPE_UINT64:
+ u.ll = va_arg(ap, PRUint64);
+ do_longlong:
+ rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ u.d = va_arg(ap, double);
+ rv = cvt_f(ss, u.d, width, prec, c, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'c':
+ u.ch = va_arg(ap, int);
+ if ((flags & _LEFT) == 0) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ rv = (*ss->stuff)(ss, &u.ch, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ if (flags & _LEFT) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(int)) {
+ type = TYPE_UINTN;
+ } else {
+ PR_ASSERT(0);
+ break;
+ }
+ radix = 16;
+ goto fetch_and_convert;
+
+#if 0
+ case 'C':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ break;
+#endif
+
+ case 'S':
+ u.S = va_arg(ap, const PRUnichar*);
+ rv = cvt_S(ss, u.S, width, prec, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 's':
+ u.s = va_arg(ap, const char*);
+ rv = cvt_s(ss, u.s, width, prec, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'n':
+ u.ip = va_arg(ap, int*);
+ if (u.ip) {
+ *u.ip = ss->cur - ss->base;
+ }
+ break;
+
+ default:
+ /* Not a % token after all... skip it */
+#if 0
+ PR_ASSERT(0);
+#endif
+ PRUnichar perct = '%';
+ rv = (*ss->stuff)(ss, &perct, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Stuff trailing NUL */
+ PRUnichar null = '\0';
+
+ rv = (*ss->stuff)(ss, &null, 1);
+
+ if( nas && ( nas != nasArray ) ){
+ PR_DELETE( nas );
+ }
+
+ return rv;
+}
+
+/************************************************************************/
+
+static int
+StringStuff(SprintfState* ss, const PRUnichar* sp, PRUint32 len)
+{
+ ptrdiff_t off = ss->cur - ss->base;
+
+ nsAString* str = NS_STATIC_CAST(nsAString*,ss->stuffclosure);
+ str->Append(sp, len);
+
+ // we can assume contiguous storage
+ nsAString::iterator begin;
+ str->BeginWriting(begin);
+ ss->base = begin.get();
+ ss->cur = ss->base + off;
+
+ return 0;
+}
+
+/*
+** Stuff routine that automatically grows the malloc'd output buffer
+** before it overflows.
+*/
+static int GrowStuff(SprintfState *ss, const PRUnichar *sp, PRUint32 len)
+{
+ ptrdiff_t off;
+ PRUnichar *newbase;
+ PRUint32 newlen;
+
+ off = ss->cur - ss->base;
+ if (off + len >= ss->maxlen) {
+ /* Grow the buffer */
+ newlen = ss->maxlen + ((len > 32) ? len : 32);
+ if (ss->base) {
+ newbase = (PRUnichar*) PR_REALLOC(ss->base, newlen*sizeof(PRUnichar));
+ } else {
+ newbase = (PRUnichar*) PR_MALLOC(newlen*sizeof(PRUnichar));
+ }
+ if (!newbase) {
+ /* Ran out of memory */
+ return -1;
+ }
+ ss->base = newbase;
+ ss->maxlen = newlen;
+ ss->cur = ss->base + off;
+ }
+
+ /* Copy data */
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen);
+ return 0;
+}
+
+/*
+** sprintf into a malloc'd buffer
+*/
+PRUnichar * nsTextFormatter::smprintf(const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUnichar *rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsmprintf(fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUint32 nsTextFormatter::ssprintf(nsAString& out, const PRUnichar* fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vssprintf(out, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+/*
+** Free memory allocated, for the caller, by smprintf
+*/
+void nsTextFormatter::smprintf_free(PRUnichar *mem)
+{
+ PR_DELETE(mem);
+}
+
+PRUint32 nsTextFormatter::vssprintf(nsAString& out, const PRUnichar* fmt, va_list ap)
+{
+ SprintfState ss;
+ ss.stuff = StringStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ ss.stuffclosure = &out;
+
+ out.Truncate();
+ int n = dosprintf(&ss, fmt, ap);
+ return n ? n - 1 : n;
+}
+
+PRUnichar * nsTextFormatter::vsmprintf(const PRUnichar *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
+/*
+** Stuff routine that discards overflow data
+*/
+static int LimitStuff(SprintfState *ss, const PRUnichar *sp, PRUint32 len)
+{
+ PRUint32 limit = ss->maxlen - (ss->cur - ss->base);
+
+ if (len > limit) {
+ len = limit;
+ }
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ return 0;
+}
+
+/*
+** sprintf into a fixed size buffer. Make sure there is a NUL at the end
+** when finished.
+*/
+PRUint32 nsTextFormatter::snprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsnprintf(out, outlen, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUint32 nsTextFormatter::vsnprintf(PRUnichar *out, PRUint32 outlen,const PRUnichar *fmt,
+ va_list ap)
+{
+ SprintfState ss;
+ PRUint32 n;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ ss.stuff = LimitStuff;
+ ss.base = out;
+ ss.cur = out;
+ ss.maxlen = outlen;
+ (void) dosprintf(&ss, fmt, ap);
+
+ /* If we added chars, and we didn't append a null, do it now. */
+ if( (ss.cur != ss.base) && (*(ss.cur - 1) != '\0') )
+ *(--ss.cur) = '\0';
+
+ n = ss.cur - ss.base;
+ return n ? n - 1 : n;
+}
+
+PRUnichar * nsTextFormatter::sprintf_append(PRUnichar *last, const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUnichar *rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsprintf_append(last, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUnichar * nsTextFormatter::vsprintf_append(PRUnichar *last, const PRUnichar *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ if (last) {
+ int lastlen = nsCRT::strlen(last);
+ ss.base = last;
+ ss.cur = last + lastlen;
+ ss.maxlen = lastlen;
+ } else {
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ }
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+#ifdef DEBUG
+PRBool nsTextFormatter::SelfTest()
+{
+ PRBool passed = PR_TRUE ;
+ nsAutoString fmt(NS_LITERAL_STRING("%3$s %4$S %1$d %2$d"));
+
+ char utf8[] = "Hello";
+ PRUnichar ucs2[]={'W', 'o', 'r', 'l', 'd', 0x4e00, 0xAc00, 0xFF45, 0x0103};
+ int d=3;
+
+
+ PRUnichar buf[256];
+ int ret;
+ ret = nsTextFormatter::snprintf(buf, 256, fmt.get(), d, 333, utf8, ucs2);
+ printf("ret = %d\n", ret);
+ nsAutoString out(buf);
+ printf("%s \n", NS_LossyConvertUCS2toASCII(out).get());
+ const PRUnichar *uout = out.get();
+ for(PRUint32 i=0;i<out.Length();i++)
+ printf("%2X ", uout[i]);
+
+ return passed;
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h
new file mode 100644
index 00000000..903ac195
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTextFormatter_h___
+#define nsTextFormatter_h___
+
+/*
+** API for PR printf like routines. Supports the following formats
+** %d - decimal
+** %u - unsigned decimal
+** %x - unsigned hex
+** %X - unsigned uppercase hex
+** %o - unsigned octal
+** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
+** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
+** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
+** %s - utf8 string
+** %S - PRUnichar string
+** %c - character
+** %p - pointer (deals with machine dependent pointer size)
+** %f - float
+** %g - float
+*/
+#include "prtypes.h"
+#include "prio.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "nscore.h"
+#include "nsAString.h"
+
+
+class NS_COM nsTextFormatter {
+
+public:
+
+/*
+** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
+** of the buffer. Returns the length of the written output, NOT including
+** the NUL, or (PRUint32)-1 if an error occurs.
+*/
+static PRUint32 snprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, ...);
+
+/*
+** sprintf into a PR_MALLOC'd buffer. Return a pointer to the malloc'd
+** buffer on success, NULL on failure. Call "smprintf_free" to release
+** the memory returned.
+*/
+static PRUnichar* smprintf(const PRUnichar *fmt, ...);
+
+
+static PRUint32 ssprintf(nsAString& out, const PRUnichar* fmt, ...);
+/*
+** Free the memory allocated, for the caller, by smprintf
+*/
+static void smprintf_free(PRUnichar *mem);
+
+/*
+** "append" sprintf into a PR_MALLOC'd buffer. "last" is the last value of
+** the PR_MALLOC'd buffer. sprintf will append data to the end of last,
+** growing it as necessary using realloc. If last is NULL, PR_sprintf_append
+** will allocate the initial string. The return value is the new value of
+** last for subsequent calls, or NULL if there is a malloc failure.
+*/
+static PRUnichar* sprintf_append(PRUnichar *last, const PRUnichar *fmt, ...);
+
+/*
+** va_list forms of the above.
+*/
+static PRUint32 vsnprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, va_list ap);
+static PRUnichar* vsmprintf(const PRUnichar *fmt, va_list ap);
+static PRUint32 vssprintf(nsAString& out, const PRUnichar *fmt, va_list ap);
+static PRUnichar* vsprintf_append(PRUnichar *last, const PRUnichar *fmt, va_list ap);
+
+#ifdef DEBUG
+static PRBool SelfTest();
+#endif
+
+
+};
+
+#endif /* nsTextFormatter_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTime.h b/src/libs/xpcom18a4/xpcom/ds/nsTime.h
new file mode 100644
index 00000000..f5c3a0ab
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTime.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTime_h__
+#define nsTime_h__
+
+#include "prtime.h"
+#include "nsInt64.h"
+#include "nscore.h"
+
+/**
+ * This class encapsulates full 64-bit time functionality and
+ * provides simple arithmetic and conversion operations.
+ */
+
+// If you ever decide that you need to add a non-inline method to this
+// class, be sure to change the class declaration to "class NS_BASE
+// nsTime".
+
+class nsTime : public nsInt64
+{
+public:
+ /**
+ * Construct the current time.
+ */
+ nsTime(void) : nsInt64(PR_Now()) {
+ }
+
+ /**
+ * Construct the time from a string.
+ */
+ nsTime(const char* dateStr, PRBool defaultToGMT) {
+ PRInt64 theTime;
+ PRStatus status = PR_ParseTimeString(dateStr, defaultToGMT, &theTime);
+ if (status == PR_SUCCESS)
+ mValue = theTime;
+ else
+ mValue = LL_ZERO;
+ }
+
+ /**
+ * Construct a time from a PRTime.
+ */
+ nsTime(const PRTime aTime) : nsInt64(aTime) {
+ }
+
+ /**
+ * Construct a time from a 64-bit value.
+ */
+ nsTime(const nsInt64& aTime) : nsInt64(aTime) {
+ }
+
+ /**
+ * Construct a time from another time.
+ */
+ nsTime(const nsTime& aTime) : nsInt64(aTime.mValue) {
+ }
+
+ // ~nsTime(void) -- XXX destructor unnecessary
+
+ /**
+ * Assign one time to another.
+ */
+ const nsTime& operator =(const nsTime& aTime) {
+ mValue = aTime.mValue;
+ return *this;
+ }
+
+ /**
+ * Convert a nsTime object to a PRTime
+ */
+ operator PRTime(void) const {
+ return mValue;
+ }
+};
+
+/**
+ * Determine if one time is strictly less than another
+ */
+inline const PRBool
+operator <(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue < aTime2.mValue;
+}
+
+/**
+ * Determine if one time is less than or equal to another
+ */
+inline const PRBool
+operator <=(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue <= aTime2.mValue;
+}
+
+/**
+ * Determine if one time is strictly greater than another
+ */
+inline const PRBool
+operator >(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue > aTime2.mValue;
+}
+
+/**
+ * Determine if one time is greater than or equal to another
+ */
+inline const PRBool
+operator >=(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue >= aTime2.mValue;
+}
+
+#endif // nsTime_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp
new file mode 100644
index 00000000..4974f562
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTimelineService.h"
+#include "prlong.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "plhash.h"
+#include "prlock.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prthread.h"
+
+#ifdef MOZ_TIMELINE
+
+#define MAXINDENT 20
+
+#ifdef XP_MAC
+static PRIntervalTime initInterval = 0;
+#endif
+
+static PRFileDesc *timelineFD = PR_STDERR;
+static PRBool gTimelineDisabled = PR_TRUE;
+
+// Notes about threading:
+// We avoid locks as we always use thread-local-storage.
+// This means every other thread has its own private copy of
+// data, and this thread can't re-enter (as our implemenation
+// doesn't call back out anywhere). Thus, we can avoid locks!
+// TLS index
+static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
+static PRUintn gTLSIndex = BAD_TLS_INDEX;
+
+class TimelineThreadData {
+public:
+ TimelineThreadData() : initTime(0), indent(0),
+ disabled(PR_TRUE), timers(nsnull) {}
+ ~TimelineThreadData() {if (timers) PL_HashTableDestroy(timers);}
+ PRTime initTime;
+ PRHashTable *timers;
+ int indent;
+ PRBool disabled;
+};
+
+/* Implementation file */
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTimelineService, nsITimelineService)
+
+static PRTime Now(void);
+
+/*
+ * Timer structure stored in a hash table to keep track of named
+ * timers.
+ */
+class nsTimelineServiceTimer {
+ public:
+ nsTimelineServiceTimer();
+ ~nsTimelineServiceTimer();
+ void start();
+
+ /*
+ * Caller passes in "now" rather than having us calculate it so
+ * that we can avoid including timer overhead in the time being
+ * measured.
+ */
+ void stop(PRTime now);
+ void reset();
+ PRTime getAccum();
+ PRTime getAccum(PRTime now);
+
+ private:
+ PRTime mAccum;
+ PRTime mStart;
+ PRInt32 mRunning;
+ PRThread *mOwnerThread; // only used for asserts - could be #if MOZ_DEBUG
+};
+
+#define TIMER_CHECK_OWNER() \
+ NS_ABORT_IF_FALSE(PR_GetCurrentThread() == mOwnerThread, \
+ "Timer used by non-owning thread")
+
+
+nsTimelineServiceTimer::nsTimelineServiceTimer()
+: mAccum(LL_ZERO), mStart(LL_ZERO), mRunning(0),
+ mOwnerThread(PR_GetCurrentThread())
+{
+}
+
+nsTimelineServiceTimer::~nsTimelineServiceTimer()
+{
+}
+
+void nsTimelineServiceTimer::start()
+{
+ TIMER_CHECK_OWNER();
+ if (!mRunning) {
+ mStart = Now();
+ }
+ mRunning++;
+}
+
+void nsTimelineServiceTimer::stop(PRTime now)
+{
+ TIMER_CHECK_OWNER();
+ mRunning--;
+ if (mRunning == 0) {
+ PRTime delta, accum;
+ LL_SUB(delta, now, mStart);
+ LL_ADD(accum, mAccum, delta);
+ mAccum = accum;
+ }
+}
+
+void nsTimelineServiceTimer::reset()
+{
+ TIMER_CHECK_OWNER();
+ mStart = 0;
+ mAccum = 0;
+}
+
+PRTime nsTimelineServiceTimer::getAccum()
+{
+ TIMER_CHECK_OWNER();
+ PRTime accum;
+
+ if (!mRunning) {
+ accum = mAccum;
+ } else {
+ PRTime delta;
+ LL_SUB(delta, Now(), mStart);
+ LL_ADD(accum, mAccum, delta);
+ }
+ return accum;
+}
+
+PRTime nsTimelineServiceTimer::getAccum(PRTime now)
+{
+ TIMER_CHECK_OWNER();
+ PRTime accum;
+
+ if (!mRunning) {
+ accum = mAccum;
+ } else {
+ PRTime delta;
+ LL_SUB(delta, now, mStart);
+ LL_ADD(accum, mAccum, delta);
+ }
+ return accum;
+}
+
+#ifdef XP_MAC
+/*
+ * PR_Now() on the Mac only gives us a resolution of seconds. Using
+ * PR_IntervalNow() gives us better resolution. with the drawback that
+ * the timeline is only good for about six hours.
+ *
+ * PR_IntervalNow() occasionally exhibits discontinuities on Windows,
+ * so we only use it on the Mac. Bleah!
+ */
+static PRTime Now(void)
+{
+ PRIntervalTime numTicks = PR_IntervalNow() - initInterval;
+ PRTime now;
+ LL_ADD(now, initTime, PR_IntervalToMilliseconds(numTicks) * 1000);
+ return now;
+}
+#else
+static PRTime Now(void)
+{
+ return PR_Now();
+}
+#endif
+
+static TimelineThreadData *GetThisThreadData()
+{
+ NS_ABORT_IF_FALSE(gTLSIndex!=BAD_TLS_INDEX, "Our TLS not initialized");
+ TimelineThreadData *new_data = nsnull;
+ TimelineThreadData *data = (TimelineThreadData *)PR_GetThreadPrivate(gTLSIndex);
+ if (data == nsnull) {
+ // First request for this thread - allocate it.
+ new_data = new TimelineThreadData();
+ if (!new_data)
+ goto done;
+
+ // Fill it
+ new_data->timers = PL_NewHashTable(100, PL_HashString, PL_CompareStrings,
+ PL_CompareValues, NULL, NULL);
+ if (new_data->timers==NULL)
+ goto done;
+ new_data->initTime = PR_Now();
+ NS_WARN_IF_FALSE(!gTimelineDisabled,
+ "Why are we creating new state when disabled?");
+ new_data->disabled = PR_FALSE;
+ data = new_data;
+ new_data = nsnull;
+ PR_SetThreadPrivate(gTLSIndex, data);
+ }
+done:
+ if (new_data) // eeek - error during creation!
+ delete new_data;
+ NS_WARN_IF_FALSE(data, "TimelineService could not get thread-local data");
+ return data;
+}
+
+extern "C" {
+ static void ThreadDestruct (void *data);
+ static PRStatus TimelineInit(void);
+};
+
+void ThreadDestruct( void *data )
+{
+ if (data)
+ delete (TimelineThreadData *)data;
+}
+
+/*
+* PRCallOnceFN that initializes stuff for the timing service.
+*/
+static PRCallOnceType initonce;
+
+PRStatus TimelineInit(void)
+{
+ char *timeStr;
+ char *fileName;
+ PRInt32 secs, msecs;
+ PRFileDesc *fd;
+ PRInt64 tmp1, tmp2;
+
+ PRStatus status = PR_NewThreadPrivateIndex( &gTLSIndex, ThreadDestruct );
+ NS_WARN_IF_FALSE(status==0, "TimelineService could not allocate TLS storage.");
+
+ timeStr = PR_GetEnv("NS_TIMELINE_INIT_TIME");
+#ifdef XP_MAC
+ initInterval = PR_IntervalNow();
+#endif
+ // NS_TIMELINE_INIT_TIME only makes sense for the main thread, so if it
+ // exists, set it there. If not, let normal thread management code take
+ // care of setting the init time.
+ if (timeStr != NULL && 2 == PR_sscanf(timeStr, "%d.%d", &secs, &msecs)) {
+ PRTime &initTime = GetThisThreadData()->initTime;
+ LL_MUL(tmp1, (PRInt64)secs, 1000000);
+ LL_MUL(tmp2, (PRInt64)msecs, 1000);
+ LL_ADD(initTime, tmp1, tmp2);
+#ifdef XP_MAC
+ initInterval -= PR_MicrosecondsToInterval(
+ (PRUint32)(PR_Now() - initTime));
+#endif
+ }
+ // Get the log file.
+#ifdef XP_MAC
+ fileName = "timeline.txt";
+#else
+ fileName = PR_GetEnv("NS_TIMELINE_LOG_FILE");
+#endif
+ if (fileName != NULL
+ && (fd = PR_Open(fileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666)) != NULL) {
+ timelineFD = fd;
+ PR_fprintf(fd,
+ "NOTE: due to asynchrony, the indentation that you see does"
+ " not necessarily correspond to nesting in the code.\n\n");
+ }
+
+ // Runtime disable of timeline
+ if (PR_GetEnv("NS_TIMELINE_ENABLE"))
+ gTimelineDisabled = PR_FALSE;
+ return PR_SUCCESS;
+}
+
+static void ParseTime(PRTime tm, PRInt32& secs, PRInt32& msecs)
+{
+ PRTime llsecs, llmsecs, tmp;
+
+ LL_DIV(llsecs, tm, 1000000);
+ LL_MOD(tmp, tm, 1000000);
+ LL_DIV(llmsecs, tmp, 1000);
+
+ LL_L2I(secs, llsecs);
+ LL_L2I(msecs, llmsecs);
+}
+
+static char *Indent(char *buf)
+{
+ int &indent = GetThisThreadData()->indent;
+ int amount = indent;
+ if (amount > MAXINDENT) {
+ amount = MAXINDENT;
+ }
+ if (amount < 0) {
+ amount = 0;
+ indent = 0;
+ PR_Write(timelineFD, "indent underflow!\n", 18);
+ }
+ while (amount--) {
+ *buf++ = ' ';
+ }
+ return buf;
+}
+
+static void PrintTime(PRTime tm, const char *text, va_list args)
+{
+ PRInt32 secs, msecs;
+ char pbuf[550], *pc, tbuf[550];
+
+ ParseTime(tm, secs, msecs);
+
+ // snprintf/write rather than fprintf because we don't want
+ // messages from multiple threads to garble one another.
+ pc = Indent(pbuf);
+ PR_vsnprintf(pc, sizeof pbuf - (pc - pbuf), text, args);
+ PR_snprintf(tbuf, sizeof tbuf, "%05d.%03d (%08p): %s\n",
+ secs, msecs, PR_GetCurrentThread(), pbuf);
+ PR_Write(timelineFD, tbuf, strlen(tbuf));
+}
+
+/*
+ * Make this public if we need it.
+ */
+static nsresult NS_TimelineMarkV(const char *text, va_list args)
+{
+ PRTime elapsed,tmp;
+
+ PR_CallOnce(&initonce, TimelineInit);
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ tmp = Now();
+ LL_SUB(elapsed, tmp, thread->initTime);
+
+ PrintTime(elapsed, text, args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineForceMark(const char *text, ...)
+{
+ va_list args;
+ va_start(args, text);
+ NS_TimelineMarkV(text, args);
+ va_end(args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineMark(const char *text, ...)
+{
+ va_list args;
+
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ va_start(args, text);
+ NS_TimelineMarkV(text, args);
+ va_end(args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineStartTimer(const char *timerName)
+{
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ timer = new nsTimelineServiceTimer;
+ if (!timer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PL_HashTableAdd(thread->timers, timerName, timer);
+ }
+ timer->start();
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineStopTimer(const char *timerName)
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ /*
+ * Strange-looking now/timer->stop() interaction is to avoid
+ * including time spent in TLS and PL_HashTableLookup in the
+ * timer.
+ */
+ PRTime now = Now();
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+
+ timer->stop(now);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineMarkTimer(const char *timerName, const char *str)
+{
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+ PRTime accum = timer->getAccum();
+
+ char buf[500];
+ PRInt32 sec, msec;
+ ParseTime(accum, sec, msec);
+ if (!str)
+ PR_snprintf(buf, sizeof buf, "%s total: %d.%03d",
+ timerName, sec, msec);
+ else
+ PR_snprintf(buf, sizeof buf, "%s total: %d.%03d (%s)",
+ timerName, sec, msec, str);
+ NS_TimelineMark(buf);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineResetTimer(const char *timerName)
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+
+ timer->reset();
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineIndent()
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ thread->indent++;
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineOutdent()
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ thread->indent--;
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineEnter(const char *text)
+{
+ nsresult rv = NS_TimelineMark("%s...", text);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_TimelineIndent();
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineLeave(const char *text)
+{
+ nsresult rv = NS_TimelineOutdent();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_TimelineMark("...%s", text);
+}
+
+nsTimelineService::nsTimelineService()
+{
+ /* member initializers and constructor code */
+}
+
+/* void mark (in string text); */
+NS_IMETHODIMP nsTimelineService::Mark(const char *text)
+{
+ return NS_TimelineMark(text);
+}
+
+/* void startTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::StartTimer(const char *timerName)
+{
+ return NS_TimelineStartTimer(timerName);
+}
+
+/* void stopTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::StopTimer(const char *timerName)
+{
+ return NS_TimelineStopTimer(timerName);
+}
+
+/* void markTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::MarkTimer(const char *timerName)
+{
+ return NS_TimelineMarkTimer(timerName);
+}
+
+/* void markTimerWithComment(in string timerName, in string comment); */
+NS_IMETHODIMP nsTimelineService::MarkTimerWithComment(const char *timerName, const char *comment)
+{
+ return NS_TimelineMarkTimer(timerName, comment);
+}
+
+/* void resetTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::ResetTimer(const char *timerName)
+{
+ return NS_TimelineResetTimer(timerName);
+}
+
+/* void indent (); */
+NS_IMETHODIMP nsTimelineService::Indent()
+{
+ return NS_TimelineIndent();
+}
+
+/* void outdent (); */
+NS_IMETHODIMP nsTimelineService::Outdent()
+{
+ return NS_TimelineOutdent();
+}
+
+/* void enter (in string text); */
+NS_IMETHODIMP nsTimelineService::Enter(const char *text)
+{
+ return NS_TimelineEnter(text);
+}
+
+/* void leave (in string text); */
+NS_IMETHODIMP nsTimelineService::Leave(const char *text)
+{
+ return NS_TimelineLeave(text);
+}
+
+#endif /* MOZ_TIMELINE */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h
new file mode 100644
index 00000000..bb579755
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsITimelineService.h"
+
+#ifdef MOZ_TIMELINE
+
+#define NS_TIMELINESERVICE_CID \
+{ /* a335edf0-3daf-11d5-b67d-000064657374 */ \
+ 0xa335edf0, \
+ 0x3daf, \
+ 0x11d5, \
+ {0xb6, 0x7d, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+#define NS_TIMELINESERVICE_CONTRACTID "@mozilla.org;timeline-service;1"
+#define NS_TIMELINESERVICE_CLASSNAME "Timeline Service"
+
+class nsTimelineService : public nsITimelineService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMELINESERVICE
+
+ nsTimelineService();
+
+private:
+ ~nsTimelineService() {}
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp
new file mode 100644
index 00000000..12033da0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsUnicharBuffer.h"
+#include "nsCRT.h"
+
+#define MIN_BUFFER_SIZE 32
+
+UnicharBufferImpl::UnicharBufferImpl()
+ : mBuffer(NULL), mSpace(0), mLength(0)
+{
+}
+
+NS_METHOD
+UnicharBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ UnicharBufferImpl* it = new UnicharBufferImpl();
+ if (it == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(it);
+ nsresult rv = it->QueryInterface(aIID, aResult);
+ NS_RELEASE(it);
+ return rv;
+}
+
+NS_IMETHODIMP
+UnicharBufferImpl::Init(PRUint32 aBufferSize)
+{
+ if (aBufferSize < MIN_BUFFER_SIZE) {
+ aBufferSize = MIN_BUFFER_SIZE;
+ }
+ mSpace = aBufferSize;
+ mLength = 0;
+ mBuffer = new PRUnichar[aBufferSize];
+ return mBuffer ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_ISUPPORTS1(UnicharBufferImpl, nsIUnicharBuffer)
+
+UnicharBufferImpl::~UnicharBufferImpl()
+{
+ if (nsnull != mBuffer) {
+ delete[] mBuffer;
+ mBuffer = nsnull;
+ }
+ mLength = 0;
+}
+
+NS_IMETHODIMP_(PRInt32)
+UnicharBufferImpl::GetLength() const
+{
+ return mLength;
+}
+
+NS_IMETHODIMP_(PRInt32)
+UnicharBufferImpl::GetBufferSize() const
+{
+ return mSpace;
+}
+
+NS_IMETHODIMP_(PRUnichar*)
+UnicharBufferImpl::GetBuffer() const
+{
+ return mBuffer;
+}
+
+NS_IMETHODIMP_(PRBool)
+UnicharBufferImpl::Grow(PRInt32 aNewSize)
+{
+ if (PRUint32(aNewSize) < MIN_BUFFER_SIZE) {
+ aNewSize = MIN_BUFFER_SIZE;
+ }
+ PRUnichar* newbuf = new PRUnichar[aNewSize];
+ if (nsnull != newbuf) {
+ if (0 != mLength) {
+ memcpy(newbuf, mBuffer, mLength * sizeof(PRUnichar));
+ }
+ delete[] mBuffer;
+ mBuffer = newbuf;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_COM nsresult
+NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize)
+{
+ nsresult rv;
+ nsIUnicharBuffer* buf;
+ rv = UnicharBufferImpl::Create(aOuter, NS_GET_IID(nsIUnicharBuffer),
+ (void**)&buf);
+ if (NS_FAILED(rv)) return rv;
+ rv = buf->Init(aBufferSize);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(buf);
+ return rv;
+ }
+ *aInstancePtrResult = buf;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h
new file mode 100644
index 00000000..d57a48ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsUnicharBuffer_h__
+#define nsUnicharBuffer_h__
+
+#include "nsIUnicharBuffer.h"
+
+class UnicharBufferImpl : public nsIUnicharBuffer {
+public:
+ UnicharBufferImpl();
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Init(PRUint32 aBufferSize);
+ NS_IMETHOD_(PRInt32) GetLength() const;
+ NS_IMETHOD_(PRInt32) GetBufferSize() const;
+ NS_IMETHOD_(PRUnichar*) GetBuffer() const;
+ NS_IMETHOD_(PRBool) Grow(PRInt32 aNewSize);
+
+ PRUnichar* mBuffer;
+ PRUint32 mSpace;
+ PRUint32 mLength;
+
+private:
+ ~UnicharBufferImpl();
+};
+
+#endif // nsUnicharBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h b/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h
new file mode 100644
index 00000000..07825385
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsUnitConversion_h__
+#define nsUnitConversion_h__
+
+#include "nscore.h"
+#include "nsCoord.h"
+#include <math.h>
+#include <float.h>
+
+#ifndef FLT_EPSILON
+// Not an ANSI compiler... oh, well. Use an IEEE value.
+#define FLT_EPSILON 1.19209290e-7f
+#endif
+/// handy constants
+#define TWIPS_PER_POINT_INT 20
+#define TWIPS_PER_POINT_FLOAT 20.0f
+#define CEIL_CONST_FLOAT (1.0f - 0.5f*FLT_EPSILON)
+#define ROUND_EXCLUSIVE_CONST_FLOAT (0.5f*CEIL_CONST_FLOAT)
+#define ROUND_CONST_FLOAT 0.5f
+
+
+/*
+ * Coord Rounding Functions
+ */
+inline nscoord NSToCoordFloor(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue) : nscoord(aValue - CEIL_CONST_FLOAT));
+}
+
+inline nscoord NSToCoordCeil(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + CEIL_CONST_FLOAT) : nscoord(aValue));
+}
+
+inline nscoord NSToCoordRound(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + ROUND_CONST_FLOAT) : nscoord(aValue - ROUND_CONST_FLOAT));
+}
+
+inline nscoord NSToCoordRoundExclusive(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + ROUND_EXCLUSIVE_CONST_FLOAT) :
+ nscoord(aValue - ROUND_EXCLUSIVE_CONST_FLOAT));
+}
+
+
+/*
+ * Int Rounding Functions
+ */
+inline PRInt32 NSToIntFloor(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue) : PRInt32(aValue - CEIL_CONST_FLOAT));
+}
+
+inline PRInt32 NSToIntCeil(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + CEIL_CONST_FLOAT) : PRInt32(aValue));
+}
+
+inline PRInt32 NSToIntRound(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + ROUND_CONST_FLOAT) : PRInt32(aValue - ROUND_CONST_FLOAT));
+}
+
+inline PRInt32 NSToIntRoundExclusive(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + ROUND_EXCLUSIVE_CONST_FLOAT) :
+ PRInt32(aValue - ROUND_EXCLUSIVE_CONST_FLOAT));
+}
+
+
+/*
+ * Twips/Points conversions
+ */
+inline nscoord NSFloatPointsToTwips(float aPoints)
+{
+ return NSToCoordRound(aPoints * TWIPS_PER_POINT_FLOAT);
+}
+
+inline nscoord NSIntPointsToTwips(PRInt32 aPoints)
+{
+ return nscoord(aPoints * TWIPS_PER_POINT_INT);
+}
+
+inline PRInt32 NSTwipsToIntPoints(nscoord aTwips)
+{
+ return NSToIntRound(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline PRInt32 NSTwipsToFloorIntPoints(nscoord aTwips)
+{
+ return NSToIntFloor(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline PRInt32 NSTwipsToCeilIntPoints(nscoord aTwips)
+{
+ return NSToIntCeil(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline float NSTwipsToFloatPoints(nscoord aTwips)
+{
+ return (float(aTwips) / TWIPS_PER_POINT_FLOAT);
+}
+
+/*
+ * Twips/Pixel conversions
+ */
+inline nscoord NSFloatPixelsToTwips(float aPixels, float aTwipsPerPixel)
+{
+ return NSToCoordRound(aPixels * aTwipsPerPixel);
+}
+
+inline nscoord NSIntPixelsToTwips(PRInt32 aPixels, float aTwipsPerPixel)
+{
+ return NSToCoordRound(float(aPixels) * aTwipsPerPixel);
+}
+
+inline float NSTwipsToFloatPixels(nscoord aTwips, float aPixelsPerTwip)
+{
+ return (float(aTwips) * aPixelsPerTwip);
+}
+
+inline PRInt32 NSTwipsToIntPixels(nscoord aTwips, float aPixelsPerTwip)
+{
+ return NSToIntRound(float(aTwips) * aPixelsPerTwip);
+}
+
+/*
+ * Twips/unit conversions
+ */
+inline nscoord NSUnitsToTwips(float aValue, float aPointsPerUnit)
+{
+ return NSToCoordRound(aValue * aPointsPerUnit * TWIPS_PER_POINT_FLOAT);
+}
+
+inline float NSTwipsToUnits(nscoord aTwips, float aUnitsPerPoint)
+{
+ return (aTwips * (aUnitsPerPoint / TWIPS_PER_POINT_FLOAT));
+}
+
+
+/// Unit conversion macros
+//@{
+#define NS_INCHES_TO_TWIPS(x) NSUnitsToTwips((x), 72.0f) // 72 points per inch
+#define NS_FEET_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 12.0f)) // 12 inches per foot
+#define NS_MILES_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 12.0f * 5280.0f)) // 5280 feet per mile
+
+#define NS_MILLIMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 0.03937f))
+#define NS_CENTIMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 0.3937f))
+#define NS_METERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 39.37f))
+#define NS_KILOMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 39370.0f))
+
+#define NS_PICAS_TO_TWIPS(x) NSUnitsToTwips((x), 12.0f) // 12 points per pica
+#define NS_DIDOTS_TO_TWIPS(x) NSUnitsToTwips((x), (16.0f / 15.0f)) // 15 didots per 16 points
+#define NS_CICEROS_TO_TWIPS(x) NSUnitsToTwips((x), (12.0f * (16.0f / 15.0f))) // 12 didots per cicero
+
+
+#define NS_TWIPS_TO_INCHES(x) NSTwipsToUnits((x), 1.0f / 72.0f)
+#define NS_TWIPS_TO_FEET(x) NSTwipsToUnits((x), 1.0f / (72.0f * 12.0f))
+#define NS_TWIPS_TO_MILES(x) NSTwipsToUnits((x), 1.0f / (72.0f * 12.0f * 5280.0f))
+
+#define NS_TWIPS_TO_MILLIMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 0.03937f))
+#define NS_TWIPS_TO_CENTIMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 0.3937f))
+#define NS_TWIPS_TO_METERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 39.37f))
+#define NS_TWIPS_TO_KILOMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 39370.0f))
+
+#define NS_TWIPS_TO_PICAS(x) NSTwipsToUnits((x), 1.0f / 12.0f)
+#define NS_TWIPS_TO_DIDOTS(x) NSTwipsToUnits((x), 1.0f / (16.0f / 15.0f))
+#define NS_TWIPS_TO_CICEROS(x) NSTwipsToUnits((x), 1.0f / (12.0f * (16.0f / 15.0f)))
+//@}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp
new file mode 100644
index 00000000..4660ccec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp
@@ -0,0 +1,304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsValueArray.h/nsValueArray.cpp code, released
+ * Dec 28, 2001.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 20-December-2001
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// nsValueArray.cpp
+//
+// Implement an array class to store unsigned integer values.
+// The maximum value must be known up front. Once known, the
+// smallest memory representation will be attempted; i.e. if the
+// maximum value was 1275, then 2 bytes (uint16) would represent each value
+// in the array instead of 4 bytes (uint32).
+//
+#include "nsValueArray.h"
+#include "nsCRT.h"
+#include "prmem.h"
+#include "prbit.h"
+
+#define NSVALUEARRAY_LINEAR_GROWBY 8
+#define NSVALUEARRAY_LINEAR_THRESHOLD 128
+
+nsValueArray::nsValueArray(nsValueArrayValue aMaxValue, nsValueArrayCount aInitialCapacity) {
+ mCount = 0;
+ mCapacity = 0;
+ mValueArray = nsnull;
+
+ PRUint8 test8 = (PRUint8)aMaxValue;
+ PRUint16 test16 = (PRUint16)aMaxValue;
+ PRUint32 test32 = (PRUint32)aMaxValue;
+ if ((nsValueArrayValue)test8 == aMaxValue) {
+ mBytesPerValue = sizeof(test8);
+ }
+ else if ((nsValueArrayValue)test16 == aMaxValue) {
+ mBytesPerValue = sizeof(test16);
+ }
+ else if ((nsValueArrayValue)test32 == aMaxValue) {
+ mBytesPerValue = sizeof(test32);
+ }
+ else {
+ NS_ASSERTION(0, "not supported yet, add it yourself...");
+ mBytesPerValue = 0;
+ }
+
+ if (aInitialCapacity) {
+ mValueArray = (PRUint8*)PR_Malloc(aInitialCapacity * mBytesPerValue);
+ if (nsnull != mValueArray) {
+ mCapacity = aInitialCapacity;
+ }
+ }
+}
+
+nsValueArray::~nsValueArray() {
+ if (nsnull != mValueArray) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ }
+}
+
+//
+// Copy it.
+//
+nsValueArray& nsValueArray::operator=(const nsValueArray& aOther) {
+ //
+ // Free off what you know if not enough space, or units differ.
+ //
+ if ((mBytesPerValue != aOther.mBytesPerValue || mCapacity < aOther.mCount) && nsnull != mValueArray) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ mCount = mCapacity = 0;
+ }
+
+ //
+ // Copy some attribs.
+ //
+ mBytesPerValue = aOther.mBytesPerValue;
+ mCount = aOther.mCount;
+
+ //
+ // Anything to do?
+ //
+ if (0 != mCount) {
+ //
+ // May need to allocate our buffer.
+ //
+ if (0 == mCapacity) {
+ mValueArray = (PRUint8*)PR_Malloc(mCount * mBytesPerValue);
+ mCapacity = mCount;
+ }
+
+ NS_ASSERTION(nsnull != mValueArray, "loss of value array assignment and original data.");
+ if (nsnull != mValueArray) {
+ memcpy(mValueArray, aOther.mValueArray, mCount * mBytesPerValue);
+ }
+ else {
+ mCount = mCapacity = 0;
+ }
+ }
+
+ return *this;
+}
+
+//
+// Insert a value into the array.
+// No validity checking other than index is done.
+//
+PRBool nsValueArray::InsertValueAt(nsValueArrayValue aValue, nsValueArrayIndex aIndex) {
+ PRBool retval = PR_FALSE;
+
+ nsValueArrayCount count = Count();
+ if (aIndex <= count) {
+ //
+ // If we're at capacity, then we'll need to grow a little.
+ //
+ if (Capacity() == count) {
+ PRUint8* reallocRes = nsnull;
+ nsValueArrayCount growBy = NSVALUEARRAY_LINEAR_GROWBY;
+
+ //
+ // Up to a particular limit we grow in small increments.
+ // Otherwise, grow exponentially.
+ //
+ if (count >= NSVALUEARRAY_LINEAR_THRESHOLD) {
+ growBy = PR_BIT(PR_CeilingLog2(count + 1)) - count;
+ }
+
+ if (nsnull == mValueArray) {
+ reallocRes = (PRUint8*)PR_Malloc((count + growBy) * mBytesPerValue);
+ }
+ else {
+ reallocRes = (PRUint8*)PR_Realloc(mValueArray, (count + growBy) * mBytesPerValue);
+ }
+ if (nsnull != reallocRes) {
+ mValueArray = reallocRes;
+ mCapacity += growBy;
+ }
+ }
+
+ //
+ // Only if we are below capacity do we continue.
+ //
+ if (Capacity() > count) {
+ //
+ // All those at and beyond the insertion point need to move.
+ //
+ if (aIndex < count) {
+ memmove(&mValueArray[(aIndex + 1) * mBytesPerValue], &mValueArray[aIndex * mBytesPerValue], (count - aIndex) * mBytesPerValue);
+ }
+
+ //
+ // Do the assignment.
+ //
+ switch (mBytesPerValue) {
+ case sizeof(PRUint8):
+ *((PRUint8*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint8)aValue;
+ NS_ASSERTION(*((PRUint8*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ case sizeof(PRUint16):
+ *((PRUint16*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint16)aValue;
+ NS_ASSERTION(*((PRUint16*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ case sizeof(PRUint32):
+ *((PRUint32*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint32)aValue;
+ NS_ASSERTION(*((PRUint32*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ default:
+ NS_ASSERTION(0, "surely you've been warned prior to this!");
+ break;
+ }
+
+ //
+ // Up the count by 1.
+ //
+ mCount++;
+ }
+ }
+
+ return retval;
+}
+
+//
+// Remove the index from the value array.
+// The array does not shrink until Compact() is invoked.
+//
+PRBool nsValueArray::RemoveValueAt(nsValueArrayIndex aIndex) {
+ PRBool retval = PR_FALSE;
+
+ nsValueArrayCount count = Count();
+ if (aIndex < count) {
+ //
+ // Move memory around if appropriate.
+ //
+ if (aIndex != (count - 1)) {
+ memmove(&mValueArray[aIndex * mBytesPerValue], &mValueArray[(aIndex + 1) * mBytesPerValue], (count - aIndex - 1) * mBytesPerValue);
+ }
+
+ //
+ // Update our count.
+ //
+ mCount--;
+ }
+
+ return retval;
+}
+
+//
+// Shrink as much as possible.
+//
+void nsValueArray::Compact() {
+ nsValueArrayCount count = Count();
+ if (Capacity() != count)
+ {
+ if (0 == count) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ mCapacity = 0;
+ }
+ else {
+ PRUint8* reallocRes = (PRUint8*)PR_Realloc(mValueArray, count * mBytesPerValue);
+ if (nsnull != reallocRes) {
+ mValueArray = reallocRes;
+ mCapacity = count;
+ }
+ }
+ }
+}
+
+//
+// Return the value at the index.
+//
+nsValueArrayValue nsValueArray::ValueAt(nsValueArrayIndex aIndex) const {
+ nsValueArrayValue retval = NSVALUEARRAY_INVALID;
+
+ if (aIndex < Count()) {
+ switch (mBytesPerValue) {
+ case sizeof(PRUint8):
+ retval = (nsValueArrayIndex)*((PRUint8*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ case sizeof(PRUint16):
+ retval = (nsValueArrayIndex)*((PRUint16*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ case sizeof(PRUint32):
+ retval = (nsValueArrayIndex)*((PRUint32*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ default:
+ NS_ASSERTION(0, "unexpected for sure.");
+ break;
+ }
+ }
+
+ return retval;
+}
+
+//
+// Return the first encountered index of the value.
+//
+nsValueArrayIndex nsValueArray::IndexOf(nsValueArrayValue aPossibleValue) const {
+ nsValueArrayIndex retval = NSVALUEARRAY_INVALID;
+ nsValueArrayIndex traverse;
+
+ for (traverse = 0; traverse < Count(); traverse++) {
+ if (aPossibleValue == ValueAt(traverse)) {
+ retval = traverse;
+ break;
+ }
+ }
+
+ return retval;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h
new file mode 100644
index 00000000..6437ca60
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsValueArray.h/nsValueArray.cpp code, released
+ * Dec 28, 2001.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 20-December-2001
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsValueArray_h___
+#define nsValueArray_h___
+
+//
+// nsValueArray.h
+//
+// Implement an array class to store unsigned integer values.
+// The maximum value must be known up front. Once known, the
+// smallest memory representation will be attempted; i.e. if the
+// maximum value was 1275, then 2 bytes (uint16) would represent each value
+// in the array instead of 4 bytes (uint32).
+//
+#include "nscore.h"
+
+typedef PRUint32 nsValueArrayCount;
+typedef PRUint32 nsValueArrayIndex;
+typedef PRUint32 nsValueArrayValue;
+#define NSVALUEARRAY_INVALID ((nsValueArrayValue)-1)
+
+class NS_COM nsValueArray {
+ public:
+ nsValueArray(nsValueArrayValue aMaxValue,
+ nsValueArrayCount aInitialCapacity = 0);
+ ~nsValueArray();
+
+ //
+ // Assignment.
+ //
+ public:
+ nsValueArray& operator=(const nsValueArray& other);
+
+ //
+ // Array size information.
+ // Ability to add more values without growing is Capacity - Count.
+ //
+ public:
+ inline nsValueArrayCount Count() const {
+ return mCount;
+ }
+
+ inline nsValueArrayCount Capacity() const {
+ return mCapacity;
+ }
+
+ void Compact();
+
+ // Removes all elements from this array
+ inline void Clear() {
+ mCount = 0;
+ }
+
+ //
+ // Array access.
+ //
+ public:
+ nsValueArrayValue ValueAt(nsValueArrayIndex aIndex) const;
+
+ inline nsValueArrayValue operator[](nsValueArrayIndex aIndex) const {
+ return ValueAt(aIndex);
+ }
+
+ nsValueArrayIndex IndexOf(nsValueArrayValue aPossibleValue) const;
+
+ inline PRBool AppendValue(nsValueArrayValue aValue) {
+ return InsertValueAt(aValue, Count());
+ }
+
+ inline PRBool RemoveValue(nsValueArrayValue aValue) {
+ return RemoveValueAt(IndexOf(aValue));
+ }
+
+ PRBool InsertValueAt(nsValueArrayValue aValue, nsValueArrayIndex aIndex);
+
+ PRBool RemoveValueAt(nsValueArrayIndex aIndex);
+
+ //
+ // Data members.
+ //
+ private:
+ nsValueArrayCount mCount;
+ nsValueArrayCount mCapacity;
+ PRUint8* mValueArray;
+ PRUint8 mBytesPerValue;
+};
+
+#endif /* nsValueArray_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp b/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp
new file mode 100644
index 00000000..09a4cda5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp
@@ -0,0 +1,2092 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsVariant.h"
+#include "nsString.h"
+#include "prprf.h"
+#include "prdtoa.h"
+#include <math.h>
+#include "nsCRT.h"
+
+/***************************************************************************/
+// Helpers for static convert functions...
+
+static nsresult String2Double(const char* aString, double* retval)
+{
+ char* next;
+ double value = PR_strtod(aString, &next);
+ if(next == aString)
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ *retval = value;
+ return NS_OK;
+}
+
+static nsresult AString2Double(const nsAString& aString, double* retval)
+{
+ char* pChars = ToNewCString(aString);
+ if(!pChars)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = String2Double(pChars, retval);
+ nsMemory::Free(pChars);
+ return rv;
+}
+
+static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
+{
+ return String2Double(PromiseFlatUTF8String(aString).get(), retval);
+}
+
+static nsresult ACString2Double(const nsACString& aString, double* retval)
+{
+ return String2Double(PromiseFlatCString(aString).get(), retval);
+}
+
+// Fills outVariant with double, PRUint32, or PRInt32.
+// Returns NS_OK, an error code, or a non-NS_OK success code
+static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
+ nsDiscriminatedUnion* outData)
+{
+ nsresult rv;
+
+ switch(inData.mType)
+ {
+ // This group results in a PRInt32...
+
+#define CASE__NUMBER_INT32(type_, member_) \
+ case nsIDataType :: type_ : \
+ outData->u.mInt32Value = inData.u. member_ ; \
+ outData->mType = nsIDataType::VTYPE_INT32; \
+ return NS_OK;
+
+ CASE__NUMBER_INT32(VTYPE_INT8, mInt8Value)
+ CASE__NUMBER_INT32(VTYPE_INT16, mInt16Value)
+ CASE__NUMBER_INT32(VTYPE_INT32, mInt32Value)
+ CASE__NUMBER_INT32(VTYPE_UINT8, mUint8Value)
+ CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
+ CASE__NUMBER_INT32(VTYPE_BOOL, mBoolValue)
+ CASE__NUMBER_INT32(VTYPE_CHAR, mCharValue)
+ CASE__NUMBER_INT32(VTYPE_WCHAR, mWCharValue)
+
+#undef CASE__NUMBER_INT32
+
+ // This group results in a PRUint32...
+
+ case nsIDataType::VTYPE_UINT32:
+ outData->u.mInt32Value = inData.u.mUint32Value;
+ outData->mType = nsIDataType::VTYPE_INT32;
+ return NS_OK;
+
+ // This group results in a double...
+
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT64:
+ // XXX Need boundary checking here.
+ // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
+ LL_L2D(outData->u.mDoubleValue, inData.u.mInt64Value);
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_FLOAT:
+ outData->u.mDoubleValue = inData.u.mFloatValue;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_DOUBLE:
+ outData->u.mDoubleValue = inData.u.mDoubleValue;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_ASTRING:
+ rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ rv = ACString2Double(*inData.u.mCStringValue,
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+
+ // This group fails...
+
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ID:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/***************************************************************************/
+// Array helpers...
+
+static void FreeArray(nsDiscriminatedUnion* data)
+{
+ NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
+ NS_ASSERTION(data->u.array.mArrayValue, "bad array");
+ NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
+
+#define CASE__FREE_ARRAY_PTR(type_, ctype_) \
+ case nsIDataType:: type_ : \
+ { \
+ ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
+ for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
+ if(*p) \
+ nsMemory::Free((char*)*p); \
+ break; \
+ }
+
+#define CASE__FREE_ARRAY_IFACE(type_, ctype_) \
+ case nsIDataType:: type_ : \
+ { \
+ ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
+ for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
+ if(*p) \
+ (*p)->Release(); \
+ break; \
+ }
+
+ switch(data->u.array.mArrayType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ break;
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
+ CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
+ CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, PRUnichar)
+ CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
+ CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ NS_ERROR("bad type in array!");
+ break;
+ }
+
+ // Free the array memory.
+ nsMemory::Free((char*)data->u.array.mArrayValue);
+
+#undef CASE__FREE_ARRAY_PTR
+#undef CASE__FREE_ARRAY_IFACE
+}
+
+static nsresult CloneArray(PRUint16 inType, const nsIID* inIID,
+ PRUint32 inCount, void* inValue,
+ PRUint16* outType, nsIID* outIID,
+ PRUint32* outCount, void** outValue)
+{
+ NS_ASSERTION(inCount, "bad param");
+ NS_ASSERTION(inValue, "bad param");
+ NS_ASSERTION(outType, "bad param");
+ NS_ASSERTION(outCount, "bad param");
+ NS_ASSERTION(outValue, "bad param");
+
+ PRUint32 allocatedValueCount = 0;
+ nsresult rv = NS_OK;
+ PRUint32 i;
+
+ // First we figure out the size of the elements for the new u.array.
+
+ size_t elementSize;
+ size_t allocSize;
+
+ switch(inType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ elementSize = sizeof(PRInt8);
+ break;
+ case nsIDataType::VTYPE_INT16:
+ elementSize = sizeof(PRInt16);
+ break;
+ case nsIDataType::VTYPE_INT32:
+ elementSize = sizeof(PRInt32);
+ break;
+ case nsIDataType::VTYPE_INT64:
+ elementSize = sizeof(PRInt64);
+ break;
+ case nsIDataType::VTYPE_UINT8:
+ elementSize = sizeof(PRUint8);
+ break;
+ case nsIDataType::VTYPE_UINT16:
+ elementSize = sizeof(PRUint16);
+ break;
+ case nsIDataType::VTYPE_UINT32:
+ elementSize = sizeof(PRUint32);
+ break;
+ case nsIDataType::VTYPE_UINT64:
+ elementSize = sizeof(PRUint64);
+ break;
+ case nsIDataType::VTYPE_FLOAT:
+ elementSize = sizeof(float);
+ break;
+ case nsIDataType::VTYPE_DOUBLE:
+ elementSize = sizeof(double);
+ break;
+ case nsIDataType::VTYPE_BOOL:
+ elementSize = sizeof(PRBool);
+ break;
+ case nsIDataType::VTYPE_CHAR:
+ elementSize = sizeof(char);
+ break;
+ case nsIDataType::VTYPE_WCHAR:
+ elementSize = sizeof(PRUnichar);
+ break;
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ case nsIDataType::VTYPE_ID:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ elementSize = sizeof(void*);
+ break;
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ NS_ERROR("bad type in array!");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+
+ // Alloc the u.array.
+
+ allocSize = inCount * elementSize;
+ *outValue = nsMemory::Alloc(allocSize);
+ if(!*outValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Clone the elements.
+
+ switch(inType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ memcpy(*outValue, inValue, allocSize);
+ break;
+
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ if(outIID)
+ *outIID = *inIID;
+ // fall through...
+ case nsIDataType::VTYPE_INTERFACE:
+ {
+ memcpy(*outValue, inValue, allocSize);
+
+ nsISupports** p = (nsISupports**) *outValue;
+ for(i = inCount; i > 0; p++, i--)
+ if(*p)
+ (*p)->AddRef();
+ break;
+ }
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ case nsIDataType::VTYPE_ID:
+ {
+ nsID** inp = (nsID**) inValue;
+ nsID** outp = (nsID**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ nsID* idp = *(inp++);
+ if(idp)
+ {
+ if(nsnull == (*(outp++) = (nsID*)
+ nsMemory::Clone((char*)idp, sizeof(nsID))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ char** inp = (char**) inValue;
+ char** outp = (char**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ char* str = *(inp++);
+ if(str)
+ {
+ if(nsnull == (*(outp++) = (char*)
+ nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ PRUnichar** inp = (PRUnichar**) inValue;
+ PRUnichar** outp = (PRUnichar**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ PRUnichar* str = *(inp++);
+ if(str)
+ {
+ if(nsnull == (*(outp++) = (PRUnichar*)
+ nsMemory::Clone(str,
+ (nsCRT::strlen(str)+1)*sizeof(PRUnichar))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ default:
+ NS_ERROR("bad type in array!");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+ *outType = inType;
+ *outCount = inCount;
+ return NS_OK;
+
+bad:
+ if(*outValue)
+ {
+ char** p = (char**) *outValue;
+ for(i = allocatedValueCount; i > 0; p++, i--)
+ if(*p)
+ nsMemory::Free(*p);
+ nsMemory::Free((char*)*outValue);
+ *outValue = nsnull;
+ }
+ return rv;
+}
+
+/***************************************************************************/
+
+#define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_) \
+ if(data_.mType == nsIDataType :: type_) { \
+ *retval_ = data_.u.member_; \
+ return NS_OK; \
+ }
+
+#define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
+/* static */ nsresult \
+nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data, \
+ Ctype_ *_retval) \
+{ \
+ TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval) \
+ nsDiscriminatedUnion tempData; \
+ nsVariant::Initialize(&tempData); \
+ nsresult rv = ToManageableNumber(data, &tempData); \
+ /* */ \
+ /* NOTE: rv may indicate a success code that we want to preserve */ \
+ /* For the final return. So all the return cases below should return */ \
+ /* this rv when indicating success. */ \
+ /* */ \
+ if(NS_FAILED(rv)) \
+ return rv; \
+ switch(tempData.mType) \
+ {
+
+#define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_INT32: \
+ *_retval = ( Ctype_ ) tempData.u.mInt32Value; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_INT32: \
+ { \
+ PRInt32 value = tempData.u.mInt32Value; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_UINT32: \
+ *_retval = ( Ctype_ ) tempData.u.mUint32Value; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
+ case nsIDataType::VTYPE_UINT32: \
+ { \
+ PRUint32 value = tempData.u.mUint32Value; \
+ if(value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ *_retval = ( Ctype_ ) tempData.u.mDoubleValue; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ { \
+ double value = tempData.u.mDoubleValue; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ { \
+ double value = tempData.u.mDoubleValue; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return (0.0 == fmod(value,1.0)) ? \
+ rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
+ }
+
+#define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
+ CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
+ CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
+
+#define NUMERIC_CONVERSION_METHOD_END \
+ default: \
+ NS_ERROR("bad type returned from ToManageableNumber"); \
+ return NS_ERROR_CANNOT_CONVERT_DATA; \
+ } \
+}
+
+#define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
+ NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
+ CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
+ NUMERIC_CONVERSION_METHOD_END
+
+/***************************************************************************/
+// These expand into full public methods...
+
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, PRUint8, Int8, (-127-1), 127)
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, PRInt16, Int16, (-32767-1), 32767)
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, PRInt32, Int32)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRInt32)
+ CASE__NUMERIC_CONVERSION_UINT32_MAX(PRInt32, 2147483647)
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRInt32, (-2147483647-1), 2147483647)
+NUMERIC_CONVERSION_METHOD_END
+
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, PRUint8, Uint8, 0, 255)
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, PRUint16, Uint16, 0, 65535)
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, PRUint32, Uint32)
+ CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(PRUint32, 0, 2147483647)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUint32)
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRUint32, 0, 4294967295U)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toFloat convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
+NUMERIC_CONVERSION_METHOD_END
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toChar convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toWChar convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, PRUnichar, WChar)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRUnichar)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUnichar)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(PRUnichar)
+NUMERIC_CONVERSION_METHOD_END
+
+#undef NUMERIC_CONVERSION_METHOD_BEGIN
+#undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
+#undef CASES__NUMERIC_CONVERSION_NORMAL
+#undef NUMERIC_CONVERSION_METHOD_END
+#undef NUMERIC_CONVERSION_METHOD_NORMAL
+
+/***************************************************************************/
+
+// Just leverage a numeric converter for bool (but restrict the values).
+// XXX Is this really what we want to do?
+
+/* static */ nsresult
+nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval)
+{
+ TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
+
+ double val;
+ nsresult rv = nsVariant::ConvertToDouble(data, &val);
+ if(NS_FAILED(rv))
+ return rv;
+ *_retval = 0.0 != val;
+ return rv;
+}
+
+/***************************************************************************/
+
+/* static */ nsresult
+nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval)
+{
+ TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
+ TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
+
+ nsDiscriminatedUnion tempData;
+ nsVariant::Initialize(&tempData);
+ nsresult rv = ToManageableNumber(data, &tempData);
+ if(NS_FAILED(rv))
+ return rv;
+ switch(tempData.mType)
+ {
+ case nsIDataType::VTYPE_INT32:
+ LL_I2L(*_retval, tempData.u.mInt32Value);
+ return rv;
+ case nsIDataType::VTYPE_UINT32:
+ LL_UI2L(*_retval, tempData.u.mUint32Value);
+ return rv;
+ case nsIDataType::VTYPE_DOUBLE:
+ // XXX should check for data loss here!
+ LL_D2L(*_retval, tempData.u.mDoubleValue);
+ return rv;
+ default:
+ NS_ERROR("bad type returned from ToManageableNumber");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval)
+{
+ return nsVariant::ConvertToInt64(data, (PRInt64 *)_retval);
+}
+
+/***************************************************************************/
+
+static PRBool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
+{
+ nsAutoString tempString;
+ nsAString* pString;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ return pid->Parse(data.u.str.mStringValue);
+ case nsIDataType::VTYPE_CSTRING:
+ return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
+ case nsIDataType::VTYPE_UTF8STRING:
+ return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ pString = data.u.mAStringValue;
+ break;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ tempString.Assign(data.u.wstr.mWStringValue);
+ pString = &tempString;
+ break;
+ default:
+ NS_ERROR("bad type in call to String2ID");
+ return PR_FALSE;
+ }
+
+ char* pChars = ToNewCString(*pString);
+ if(!pChars)
+ return PR_FALSE;
+ PRBool result = pid->Parse(pChars);
+ nsMemory::Free(pChars);
+ return result;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
+{
+ nsID id;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ID:
+ *_retval = data.u.mIDValue;
+ return NS_OK;
+ case nsIDataType::VTYPE_INTERFACE:
+ *_retval = NS_GET_IID(nsISupports);
+ return NS_OK;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ *_retval = data.u.iface.mInterfaceID;
+ return NS_OK;
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ if(!String2ID(data, &id))
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ *_retval = id;
+ return NS_OK;
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/***************************************************************************/
+
+static nsresult ToString(const nsDiscriminatedUnion& data,
+ nsACString & outString)
+{
+ char* ptr;
+
+ switch(data.mType)
+ {
+ // all the stuff we don't handle...
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_WCHAR:
+ NS_ERROR("ToString being called for a string type - screwy logic!");
+ // fall through...
+
+ // XXX We might want stringified versions of these... ???
+
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+
+ // nsID has its own text formater.
+
+ case nsIDataType::VTYPE_ID:
+ ptr = data.u.mIDValue.ToString();
+ if(!ptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+ outString.Assign(ptr);
+ nsMemory::Free(ptr);
+ return NS_OK;
+
+ // the rest can be PR_smprintf'd and use common code.
+
+#define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
+ case nsIDataType :: type_ : \
+ ptr = PR_smprintf( format_ , (cast_) data.u. member_ ); \
+ break;
+
+ CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", PRInt64, mInt64Value)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", PRInt64, mUint64Value)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_FLOAT, "%f", float, mFloatValue)
+ CASE__SMPRINTF_NUMBER(VTYPE_DOUBLE, "%f", double, mDoubleValue)
+
+ // XXX Would we rather print "true" / "false" ?
+ CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
+
+#undef CASE__SMPRINTF_NUMBER
+ }
+
+ if(!ptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+ outString.Assign(ptr);
+ PR_smprintf_free(ptr);
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
+ nsAString & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ _retval.Assign(*data.u.mAStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ CopyASCIItoUCS2(*data.u.mCStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ _retval.Assign(data.u.wstr.mWStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ CopyASCIItoUCS2(nsDependentCString(data.u.str.mStringValue,
+ data.u.str.mStringLength),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ _retval.Assign(data.u.mWCharValue);
+ return NS_OK;
+ default:
+ {
+ nsCAutoString tempCString;
+ nsresult rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ CopyASCIItoUTF16(tempCString, _retval);
+ return NS_OK;
+ }
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
+ nsACString & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ CopyUCS2toASCII(*data.u.mAStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ _retval.Assign(*data.u.mCStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ // XXX This is an extra copy that should be avoided
+ // once Jag lands support for UTF8String and associated
+ // conversion methods.
+ CopyUCS2toASCII(NS_ConvertUTF8toUCS2(*data.u.mUTF8StringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ _retval.Assign(*data.u.str.mStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength), _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ {
+ const PRUnichar* str = &data.u.mWCharValue;
+ CopyUCS2toASCII(Substring(str, str + 1), _retval);
+ return NS_OK;
+ }
+ default:
+ return ToString(data, _retval);
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
+ nsAUTF8String & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ // XXX Extra copy, can be removed if we're sure CSTRING can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ _retval.Assign(*data.u.mUTF8StringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ // XXX Extra copy, can be removed if we're sure CHAR_STR can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ // XXX Extra copy, can be removed if we're sure CHAR_STR can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
+ nsDependentCString(data.u.str.mStringValue,
+ data.u.str.mStringLength)), _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ {
+ const PRUnichar* str = &data.u.mWCharValue;
+ CopyUTF16toUTF8(Substring(str, str + 1), _retval);
+ return NS_OK;
+ }
+ default:
+ {
+ nsCAutoString tempCString;
+ nsresult rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ // XXX Extra copy, can be removed if we're sure tempCString can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
+ return NS_OK;
+ }
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
+{
+ PRUint32 ignored;
+ return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
+}
+
+/* static */ nsresult
+nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval)
+{
+ PRUint32 ignored;
+ return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
+}
+
+/* static */ nsresult
+nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
+ PRUint32 *size, char **str)
+{
+ nsAutoString tempString;
+ nsCAutoString tempCString;
+ nsresult rv;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ *size = data.u.mAStringValue->Length();
+ *str = ToNewCString(*data.u.mAStringValue);
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ *size = data.u.mCStringValue->Length();
+ *str = ToNewCString(*data.u.mCStringValue);
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ {
+ // XXX This is doing 1 extra copy. Need to fix this
+ // when Jag lands UTF8String
+ // we want:
+ // *size = *data.mUTF8StringValue->Length();
+ // *str = ToNewCString(*data.mUTF8StringValue);
+ // But this will have to do for now.
+ NS_ConvertUTF8toUCS2 tempString(*data.u.mUTF8StringValue);
+ *size = tempString.Length();
+ *str = ToNewCString(tempString);
+ break;
+ }
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ nsDependentCString cString(data.u.str.mStringValue);
+ *size = cString.Length();
+ *str = ToNewCString(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue);
+ *size = string.Length();
+ *str = ToNewCString(string);
+ break;
+ }
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+ nsDependentCString cString(data.u.str.mStringValue,
+ data.u.str.mStringLength);
+ *size = cString.Length();
+ *str = ToNewCString(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength);
+ *size = string.Length();
+ *str = ToNewCString(string);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ tempString.Assign(data.u.mWCharValue);
+ *size = tempString.Length();
+ *str = ToNewCString(tempString);
+ break;
+ default:
+ rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ *size = tempCString.Length();
+ *str = ToNewCString(tempCString);
+ break;
+ }
+
+ return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+/* static */ nsresult
+nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
+ PRUint32 *size, PRUnichar **str)
+{
+ nsAutoString tempString;
+ nsCAutoString tempCString;
+ nsresult rv;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ *size = data.u.mAStringValue->Length();
+ *str = ToNewUnicode(*data.u.mAStringValue);
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ *size = data.u.mCStringValue->Length();
+ *str = ToNewUnicode(*data.u.mCStringValue);
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ {
+ *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
+ break;
+ }
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ nsDependentCString cString(data.u.str.mStringValue);
+ *size = cString.Length();
+ *str = ToNewUnicode(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue);
+ *size = string.Length();
+ *str = ToNewUnicode(string);
+ break;
+ }
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+ nsDependentCString cString(data.u.str.mStringValue,
+ data.u.str.mStringLength);
+ *size = cString.Length();
+ *str = ToNewUnicode(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength);
+ *size = string.Length();
+ *str = ToNewUnicode(string);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ tempString.Assign(data.u.mWCharValue);
+ *size = tempString.Length();
+ *str = ToNewUnicode(tempString);
+ break;
+ default:
+ rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ *size = tempCString.Length();
+ *str = ToNewUnicode(tempCString);
+ break;
+ }
+
+ return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
+ nsISupports **_retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ if (data.u.iface.mInterfaceValue) {
+ return data.u.iface.mInterfaceValue->
+ QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
+ } else {
+ *_retval = nsnull;
+ return NS_OK;
+ }
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
+ void * *iface)
+{
+ const nsIID* piid;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_INTERFACE:
+ piid = &NS_GET_IID(nsISupports);
+ break;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ piid = &data.u.iface.mInterfaceID;
+ break;
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+ *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
+ if(!*iid)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (data.u.iface.mInterfaceValue) {
+ return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
+ }
+
+ *iface = nsnull;
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type,
+ nsIID* iid, PRUint32 *count, void * *ptr)
+{
+ // XXX perhaps we'd like to add support for converting each of the various
+ // types into an array containing one element of that type. We can leverage
+ // CloneArray to do this if we want to support this.
+
+ if(data.mType == nsIDataType::VTYPE_ARRAY)
+ return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
+ data.u.array.mArrayCount, data.u.array.mArrayValue,
+ type, iid, count, ptr);
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+/***************************************************************************/
+// static setter functions...
+
+#define DATA_SETTER_PROLOGUE(data_) \
+ nsVariant::Cleanup(data_);
+
+#define DATA_SETTER_EPILOGUE(data_, type_) \
+ data_->mType = nsIDataType :: type_; \
+ return NS_OK;
+
+#define DATA_SETTER(data_, type_, member_, value_) \
+ DATA_SETTER_PROLOGUE(data_) \
+ data_->u.member_ = value_; \
+ DATA_SETTER_EPILOGUE(data_, type_)
+
+#define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_) \
+ DATA_SETTER_PROLOGUE(data_) \
+ data_->u.member_ = cast_ value_; \
+ DATA_SETTER_EPILOGUE(data_, type_)
+
+
+/********************************************/
+
+#define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ { \
+
+#define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
+ rv = aValue->GetAs##name_ (&(data->u. member_ ));
+
+#define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
+ rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
+
+#define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
+ if(NS_SUCCEEDED(rv)) \
+ { \
+ data->mType = nsIDataType :: type_ ; \
+ } \
+ break; \
+ }
+
+#define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
+ case nsIDataType :: type_ : \
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
+
+#define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
+ case nsIDataType :: type_ : \
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
+
+
+/* static */ nsresult
+nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
+{
+ PRUint16 type;
+ nsresult rv;
+
+ nsVariant::Cleanup(data);
+
+ rv = aValue->GetDataType(&type);
+ if(NS_FAILED(rv))
+ return rv;
+
+ switch(type)
+ {
+ CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (PRUint8*), mInt8Value,
+ Int8)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL , mBoolValue, Bool)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
+
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
+ data->u.mAStringValue = new nsString();
+ if(!data->u.mAStringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsAString(*data->u.mAStringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mAStringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
+
+ case nsIDataType::VTYPE_CSTRING:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
+ data->u.mCStringValue = new nsCString();
+ if(!data->u.mCStringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsACString(*data->u.mCStringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mCStringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
+
+ case nsIDataType::VTYPE_UTF8STRING:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
+ data->u.mUTF8StringValue = new nsUTF8String();
+ if(!data->u.mUTF8StringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mUTF8StringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
+
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
+ rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
+ &data->u.str.mStringValue);
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
+
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
+ // XXX This iid handling is ugly!
+ nsIID* iid;
+ rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
+ if(NS_SUCCEEDED(rv))
+ {
+ data->u.iface.mInterfaceID = *iid;
+ nsMemory::Free((char*)iid);
+ }
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
+
+ case nsIDataType::VTYPE_ARRAY:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
+ rv = aValue->GetAsArray(&data->u.array.mArrayType,
+ &data->u.array.mArrayInterfaceID,
+ &data->u.array.mArrayCount,
+ &data->u.array.mArrayValue);
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
+
+ case nsIDataType::VTYPE_VOID:
+ rv = nsVariant::SetToVoid(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ rv = nsVariant::SetToEmptyArray(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY:
+ rv = nsVariant::SetToEmpty(data);
+ break;
+ default:
+ NS_ERROR("bad type in variant!");
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+/* static */ nsresult
+nsVariant::SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue)
+{
+ DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (PRUint8), aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
+{
+ DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
+{
+ DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromBool(nsDiscriminatedUnion* data, PRBool aValue)
+{
+ DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
+{
+ DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue)
+{
+ DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
+{
+ DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mAStringValue = new nsString(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromACString(nsDiscriminatedUnion* data,
+ const nsACString & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mCStringValue = new nsCString(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
+ const nsAUTF8String & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ return SetFromStringWithSize(data, strlen(aValue), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ return SetFromWStringWithSize(data, nsCRT::strlen(aValue), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
+{
+ return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
+ nsISupports *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ NS_IF_ADDREF(aValue);
+ data->u.iface.mInterfaceValue = aValue;
+ data->u.iface.mInterfaceID = iid;
+ DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
+}
+/* static */ nsresult
+nsVariant::SetFromArray(nsDiscriminatedUnion* data, PRUint16 type,
+ const nsIID* iid, PRUint32 count, void * aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue || !count)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv = CloneArray(type, iid, count, aValue,
+ &data->u.array.mArrayType,
+ &data->u.array.mArrayInterfaceID,
+ &data->u.array.mArrayCount,
+ &data->u.array.mArrayValue);
+ if(NS_FAILED(rv))
+ return rv;
+ DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
+}
+/* static */ nsresult
+nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ if(!(data->u.str.mStringValue =
+ (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
+ return NS_ERROR_OUT_OF_MEMORY;
+ data->u.str.mStringLength = size;
+ DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
+}
+/* static */ nsresult
+nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ if(!(data->u.wstr.mWStringValue =
+ (PRUnichar*) nsMemory::Clone(aValue, (size+1)*sizeof(PRUnichar))))
+ return NS_ERROR_OUT_OF_MEMORY;
+ data->u.wstr.mWStringLength = size;
+ DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
+}
+/* static */ nsresult
+nsVariant::SetToVoid(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
+}
+/* static */ nsresult
+nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
+}
+/* static */ nsresult
+nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
+}
+
+/***************************************************************************/
+
+/* static */ nsresult
+nsVariant::Initialize(nsDiscriminatedUnion* data)
+{
+ data->mType = nsIDataType::VTYPE_EMPTY;
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::Cleanup(nsDiscriminatedUnion* data)
+{
+ switch(data->mType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ID:
+ break;
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ delete data->u.mAStringValue;
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ delete data->u.mCStringValue;
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ delete data->u.mUTF8StringValue;
+ break;
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ nsMemory::Free((char*)data->u.str.mStringValue);
+ break;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ nsMemory::Free((char*)data->u.wstr.mWStringValue);
+ break;
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ NS_IF_RELEASE(data->u.iface.mInterfaceValue);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ FreeArray(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ break;
+ default:
+ NS_ERROR("bad type in variant!");
+ break;
+ }
+
+ data->mType = nsIDataType::VTYPE_EMPTY;
+ return NS_OK;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+// members...
+
+NS_IMPL_ISUPPORTS2(nsVariant, nsIVariant, nsIWritableVariant)
+
+nsVariant::nsVariant()
+ : mWritable(PR_TRUE)
+{
+ nsVariant::Initialize(&mData);
+
+#ifdef DEBUG
+ {
+ // Assert that the nsIDataType consts match the values #defined in
+ // xpt_struct.h. Bad things happen somewhere if they don't.
+ struct THE_TYPES {PRUint16 a; PRUint16 b;};
+ static const THE_TYPES array[] = {
+ {nsIDataType::VTYPE_INT8 , TD_INT8 },
+ {nsIDataType::VTYPE_INT16 , TD_INT16 },
+ {nsIDataType::VTYPE_INT32 , TD_INT32 },
+ {nsIDataType::VTYPE_INT64 , TD_INT64 },
+ {nsIDataType::VTYPE_UINT8 , TD_UINT8 },
+ {nsIDataType::VTYPE_UINT16 , TD_UINT16 },
+ {nsIDataType::VTYPE_UINT32 , TD_UINT32 },
+ {nsIDataType::VTYPE_UINT64 , TD_UINT64 },
+ {nsIDataType::VTYPE_FLOAT , TD_FLOAT },
+ {nsIDataType::VTYPE_DOUBLE , TD_DOUBLE },
+ {nsIDataType::VTYPE_BOOL , TD_BOOL },
+ {nsIDataType::VTYPE_CHAR , TD_CHAR },
+ {nsIDataType::VTYPE_WCHAR , TD_WCHAR },
+ {nsIDataType::VTYPE_VOID , TD_VOID },
+ {nsIDataType::VTYPE_ID , TD_PNSIID },
+ {nsIDataType::VTYPE_DOMSTRING , TD_DOMSTRING },
+ {nsIDataType::VTYPE_CHAR_STR , TD_PSTRING },
+ {nsIDataType::VTYPE_WCHAR_STR , TD_PWSTRING },
+ {nsIDataType::VTYPE_INTERFACE , TD_INTERFACE_TYPE },
+ {nsIDataType::VTYPE_INTERFACE_IS , TD_INTERFACE_IS_TYPE},
+ {nsIDataType::VTYPE_ARRAY , TD_ARRAY },
+ {nsIDataType::VTYPE_STRING_SIZE_IS , TD_PSTRING_SIZE_IS },
+ {nsIDataType::VTYPE_WSTRING_SIZE_IS , TD_PWSTRING_SIZE_IS },
+ {nsIDataType::VTYPE_UTF8STRING , TD_UTF8STRING },
+ {nsIDataType::VTYPE_CSTRING , TD_CSTRING },
+ {nsIDataType::VTYPE_ASTRING , TD_ASTRING }
+ };
+ static const int length = sizeof(array)/sizeof(array[0]);
+ static PRBool inited = PR_FALSE;
+ if(!inited)
+ {
+ for(int i = 0; i < length; i++)
+ NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
+ inited = PR_TRUE;
+ }
+ }
+#endif
+}
+
+nsVariant::~nsVariant()
+{
+ nsVariant::Cleanup(&mData);
+}
+
+// For all the data getters we just forward to the static (and sharable)
+// 'ConvertTo' functions.
+
+/* readonly attribute PRUint16 dataType; */
+NS_IMETHODIMP nsVariant::GetDataType(PRUint16 *aDataType)
+{
+ *aDataType = mData.mType;
+ return NS_OK;
+}
+
+/* PRUint8 getAsInt8 (); */
+NS_IMETHODIMP nsVariant::GetAsInt8(PRUint8 *_retval)
+{
+ return nsVariant::ConvertToInt8(mData, _retval);
+}
+
+/* PRInt16 getAsInt16 (); */
+NS_IMETHODIMP nsVariant::GetAsInt16(PRInt16 *_retval)
+{
+ return nsVariant::ConvertToInt16(mData, _retval);
+}
+
+/* PRInt32 getAsInt32 (); */
+NS_IMETHODIMP nsVariant::GetAsInt32(PRInt32 *_retval)
+{
+ return nsVariant::ConvertToInt32(mData, _retval);
+}
+
+/* PRInt64 getAsInt64 (); */
+NS_IMETHODIMP nsVariant::GetAsInt64(PRInt64 *_retval)
+{
+ return nsVariant::ConvertToInt64(mData, _retval);
+}
+
+/* PRUint8 getAsUint8 (); */
+NS_IMETHODIMP nsVariant::GetAsUint8(PRUint8 *_retval)
+{
+ return nsVariant::ConvertToUint8(mData, _retval);
+}
+
+/* PRUint16 getAsUint16 (); */
+NS_IMETHODIMP nsVariant::GetAsUint16(PRUint16 *_retval)
+{
+ return nsVariant::ConvertToUint16(mData, _retval);
+}
+
+/* PRUint32 getAsUint32 (); */
+NS_IMETHODIMP nsVariant::GetAsUint32(PRUint32 *_retval)
+{
+ return nsVariant::ConvertToUint32(mData, _retval);
+}
+
+/* PRUint64 getAsUint64 (); */
+NS_IMETHODIMP nsVariant::GetAsUint64(PRUint64 *_retval)
+{
+ return nsVariant::ConvertToUint64(mData, _retval);
+}
+
+/* float getAsFloat (); */
+NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
+{
+ return nsVariant::ConvertToFloat(mData, _retval);
+}
+
+/* double getAsDouble (); */
+NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
+{
+ return nsVariant::ConvertToDouble(mData, _retval);
+}
+
+/* PRBool getAsBool (); */
+NS_IMETHODIMP nsVariant::GetAsBool(PRBool *_retval)
+{
+ return nsVariant::ConvertToBool(mData, _retval);
+}
+
+/* char getAsChar (); */
+NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
+{
+ return nsVariant::ConvertToChar(mData, _retval);
+}
+
+/* wchar getAsWChar (); */
+NS_IMETHODIMP nsVariant::GetAsWChar(PRUnichar *_retval)
+{
+ return nsVariant::ConvertToWChar(mData, _retval);
+}
+
+/* [notxpcom] nsresult getAsID (out nsID retval); */
+NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
+{
+ return nsVariant::ConvertToID(mData, retval);
+}
+
+/* AString getAsAString (); */
+NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
+{
+ return nsVariant::ConvertToAString(mData, _retval);
+}
+
+/* DOMString getAsDOMString (); */
+NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
+{
+ // A DOMString maps to an AString internally, so we can re-use
+ // ConvertToAString here.
+ return nsVariant::ConvertToAString(mData, _retval);
+}
+
+/* ACString getAsACString (); */
+NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
+{
+ return nsVariant::ConvertToACString(mData, _retval);
+}
+
+/* AUTF8String getAsAUTF8String (); */
+NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
+{
+ return nsVariant::ConvertToAUTF8String(mData, _retval);
+}
+
+/* string getAsString (); */
+NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
+{
+ return nsVariant::ConvertToString(mData, _retval);
+}
+
+/* wstring getAsWString (); */
+NS_IMETHODIMP nsVariant::GetAsWString(PRUnichar **_retval)
+{
+ return nsVariant::ConvertToWString(mData, _retval);
+}
+
+/* nsISupports getAsISupports (); */
+NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
+{
+ return nsVariant::ConvertToISupports(mData, _retval);
+}
+
+/* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
+NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
+{
+ return nsVariant::ConvertToInterface(mData, iid, iface);
+}
+
+/* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
+NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
+{
+ return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
+}
+
+/* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
+NS_IMETHODIMP nsVariant::GetAsStringWithSize(PRUint32 *size, char **str)
+{
+ return nsVariant::ConvertToStringWithSize(mData, size, str);
+}
+
+/* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
+NS_IMETHODIMP nsVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
+{
+ return nsVariant::ConvertToWStringWithSize(mData, size, str);
+}
+
+/***************************************************************************/
+
+/* attribute PRBool writable; */
+NS_IMETHODIMP nsVariant::GetWritable(PRBool *aWritable)
+{
+ *aWritable = mWritable;
+ return NS_OK;
+}
+NS_IMETHODIMP nsVariant::SetWritable(PRBool aWritable)
+{
+ if(!mWritable && aWritable)
+ return NS_ERROR_FAILURE;
+ mWritable = aWritable;
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+// For all the data setters we just forward to the static (and sharable)
+// 'SetFrom' functions.
+
+/* void setAsInt8 (in PRUint8 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt8(PRUint8 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt8(&mData, aValue);
+}
+
+/* void setAsInt16 (in PRInt16 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt16(PRInt16 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt16(&mData, aValue);
+}
+
+/* void setAsInt32 (in PRInt32 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt32(PRInt32 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt32(&mData, aValue);
+}
+
+/* void setAsInt64 (in PRInt64 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt64(PRInt64 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt64(&mData, aValue);
+}
+
+/* void setAsUint8 (in PRUint8 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint8(PRUint8 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint8(&mData, aValue);
+}
+
+/* void setAsUint16 (in PRUint16 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint16(PRUint16 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint16(&mData, aValue);
+}
+
+/* void setAsUint32 (in PRUint32 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint32(PRUint32 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint32(&mData, aValue);
+}
+
+/* void setAsUint64 (in PRUint64 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint64(PRUint64 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint64(&mData, aValue);
+}
+
+/* void setAsFloat (in float aValue); */
+NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromFloat(&mData, aValue);
+}
+
+/* void setAsDouble (in double aValue); */
+NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromDouble(&mData, aValue);
+}
+
+/* void setAsBool (in PRBool aValue); */
+NS_IMETHODIMP nsVariant::SetAsBool(PRBool aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromBool(&mData, aValue);
+}
+
+/* void setAsChar (in char aValue); */
+NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromChar(&mData, aValue);
+}
+
+/* void setAsWChar (in wchar aValue); */
+NS_IMETHODIMP nsVariant::SetAsWChar(PRUnichar aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWChar(&mData, aValue);
+}
+
+/* void setAsID (in nsIDRef aValue); */
+NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromID(&mData, aValue);
+}
+
+/* void setAsAString (in AString aValue); */
+NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromAString(&mData, aValue);
+}
+
+/* void setAsDOMString (in DOMString aValue); */
+NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+
+ // A DOMString maps to an AString internally, so we can re-use
+ // SetFromAString here.
+ return nsVariant::SetFromAString(&mData, aValue);
+}
+
+/* void setAsACString (in ACString aValue); */
+NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromACString(&mData, aValue);
+}
+
+/* void setAsAUTF8String (in AUTF8String aValue); */
+NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromAUTF8String(&mData, aValue);
+}
+
+/* void setAsString (in string aValue); */
+NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromString(&mData, aValue);
+}
+
+/* void setAsWString (in wstring aValue); */
+NS_IMETHODIMP nsVariant::SetAsWString(const PRUnichar *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWString(&mData, aValue);
+}
+
+/* void setAsISupports (in nsISupports aValue); */
+NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromISupports(&mData, aValue);
+}
+
+/* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
+NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
+}
+
+/* [noscript] void setAsArray (in PRUint16 type, in nsIIDPtr iid, in PRUint32 count, in voidPtr ptr); */
+NS_IMETHODIMP nsVariant::SetAsArray(PRUint16 type, const nsIID * iid, PRUint32 count, void * ptr)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
+}
+
+/* void setAsStringWithSize (in PRUint32 size, [size_is (size)] in string str); */
+NS_IMETHODIMP nsVariant::SetAsStringWithSize(PRUint32 size, const char *str)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromStringWithSize(&mData, size, str);
+}
+
+/* void setAsWStringWithSize (in PRUint32 size, [size_is (size)] in wstring str); */
+NS_IMETHODIMP nsVariant::SetAsWStringWithSize(PRUint32 size, const PRUnichar *str)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWStringWithSize(&mData, size, str);
+}
+
+/* void setAsVoid (); */
+NS_IMETHODIMP nsVariant::SetAsVoid()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToVoid(&mData);
+}
+
+/* void setAsEmpty (); */
+NS_IMETHODIMP nsVariant::SetAsEmpty()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToEmpty(&mData);
+}
+
+/* void setAsEmptyArray (); */
+NS_IMETHODIMP nsVariant::SetAsEmptyArray()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToEmptyArray(&mData);
+}
+
+/* void setFromVariant (in nsIVariant aValue); */
+NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromVariant(&mData, aValue);
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVariant.h b/src/libs/xpcom18a4/xpcom/ds/nsVariant.h
new file mode 100644
index 00000000..393e745f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVariant.h
@@ -0,0 +1,203 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsIVariant.h"
+#include "nsStringFwd.h"
+#include "xpt_struct.h"
+
+/**
+ * Map the nsAUTF8String, nsUTF8String classes to the nsACString and
+ * nsCString classes respectively for now. These defines need to be removed
+ * once Jag lands his nsUTF8String implementation.
+ */
+#define nsAUTF8String nsACString
+#define nsUTF8String nsCString
+#define PromiseFlatUTF8String PromiseFlatCString
+
+/**
+ * nsDiscriminatedUnion is a type that nsIVariant implementors *may* use
+ * to hold underlying data. It has no methods. So, its use requires no linkage
+ * to the xpcom module.
+ */
+
+struct nsDiscriminatedUnion
+{
+ union {
+ PRInt8 mInt8Value;
+ PRInt16 mInt16Value;
+ PRInt32 mInt32Value;
+ PRInt64 mInt64Value;
+ PRUint8 mUint8Value;
+ PRUint16 mUint16Value;
+ PRUint32 mUint32Value;
+ PRUint64 mUint64Value;
+ float mFloatValue;
+ double mDoubleValue;
+ PRBool mBoolValue;
+ char mCharValue;
+ PRUnichar mWCharValue;
+ nsIID mIDValue;
+ nsAString* mAStringValue;
+ nsAUTF8String* mUTF8StringValue;
+ nsACString* mCStringValue;
+ struct {
+ nsISupports* mInterfaceValue;
+ nsIID mInterfaceID;
+ } iface;
+ struct {
+ nsIID mArrayInterfaceID;
+ void* mArrayValue;
+ PRUint32 mArrayCount;
+ PRUint16 mArrayType;
+ } array;
+ struct {
+ char* mStringValue;
+ PRUint32 mStringLength;
+ } str;
+ struct {
+ PRUnichar* mWStringValue;
+ PRUint32 mWStringLength;
+ } wstr;
+ } u;
+ PRUint16 mType;
+};
+
+/**
+ * nsVariant implements the generic variant support. The xpcom module registers
+ * a factory (see NS_VARIANT_CONTRACTID in nsIVariant.idl) that will create
+ * these objects. They are created 'empty' and 'writable'.
+ *
+ * nsIVariant users won't usually need to see this class.
+ *
+ * This class also has static helper methods that nsIVariant *implementors* can
+ * use to help them do all the 'standard' nsIVariant data conversions.
+ */
+
+class NS_COM nsVariant : public nsIWritableVariant
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIVARIANT
+ NS_DECL_NSIWRITABLEVARIANT
+
+ nsVariant();
+
+ static nsresult Initialize(nsDiscriminatedUnion* data);
+ static nsresult Cleanup(nsDiscriminatedUnion* data);
+
+ static nsresult ConvertToInt8(const nsDiscriminatedUnion& data, PRUint8 *_retval);
+ static nsresult ConvertToInt16(const nsDiscriminatedUnion& data, PRInt16 *_retval);
+ static nsresult ConvertToInt32(const nsDiscriminatedUnion& data, PRInt32 *_retval);
+ static nsresult ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval);
+ static nsresult ConvertToUint8(const nsDiscriminatedUnion& data, PRUint8 *_retval);
+ static nsresult ConvertToUint16(const nsDiscriminatedUnion& data, PRUint16 *_retval);
+ static nsresult ConvertToUint32(const nsDiscriminatedUnion& data, PRUint32 *_retval);
+ static nsresult ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval);
+ static nsresult ConvertToFloat(const nsDiscriminatedUnion& data, float *_retval);
+ static nsresult ConvertToDouble(const nsDiscriminatedUnion& data, double *_retval);
+ static nsresult ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval);
+ static nsresult ConvertToChar(const nsDiscriminatedUnion& data, char *_retval);
+ static nsresult ConvertToWChar(const nsDiscriminatedUnion& data, PRUnichar *_retval);
+ static nsresult ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval);
+ static nsresult ConvertToAString(const nsDiscriminatedUnion& data, nsAString & _retval);
+ static nsresult ConvertToAUTF8String(const nsDiscriminatedUnion& data, nsAUTF8String & _retval);
+ static nsresult ConvertToACString(const nsDiscriminatedUnion& data, nsACString & _retval);
+ static nsresult ConvertToString(const nsDiscriminatedUnion& data, char **_retval);
+ static nsresult ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval);
+ static nsresult ConvertToISupports(const nsDiscriminatedUnion& data, nsISupports **_retval);
+ static nsresult ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid, void * *iface);
+ static nsresult ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type, nsIID* iid, PRUint32 *count, void * *ptr);
+ static nsresult ConvertToStringWithSize(const nsDiscriminatedUnion& data, PRUint32 *size, char **str);
+ static nsresult ConvertToWStringWithSize(const nsDiscriminatedUnion& data, PRUint32 *size, PRUnichar **str);
+
+ static nsresult SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue);
+
+ static nsresult SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue);
+ static nsresult SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue);
+ static nsresult SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue);
+ static nsresult SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue);
+ static nsresult SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue);
+ static nsresult SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue);
+ static nsresult SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue);
+ static nsresult SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue);
+ static nsresult SetFromFloat(nsDiscriminatedUnion* data, float aValue);
+ static nsresult SetFromDouble(nsDiscriminatedUnion* data, double aValue);
+ static nsresult SetFromBool(nsDiscriminatedUnion* data, PRBool aValue);
+ static nsresult SetFromChar(nsDiscriminatedUnion* data, char aValue);
+ static nsresult SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue);
+ static nsresult SetFromID(nsDiscriminatedUnion* data, const nsID & aValue);
+ static nsresult SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue);
+ static nsresult SetFromAUTF8String(nsDiscriminatedUnion* data, const nsAUTF8String & aValue);
+ static nsresult SetFromACString(nsDiscriminatedUnion* data, const nsACString & aValue);
+ static nsresult SetFromString(nsDiscriminatedUnion* data, const char *aValue);
+ static nsresult SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue);
+ static nsresult SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue);
+ static nsresult SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid, nsISupports *aValue);
+ static nsresult SetFromArray(nsDiscriminatedUnion* data, PRUint16 type, const nsIID* iid, PRUint32 count, void * aValue);
+ static nsresult SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue);
+ static nsresult SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue);
+
+ static nsresult SetToVoid(nsDiscriminatedUnion* data);
+ static nsresult SetToEmpty(nsDiscriminatedUnion* data);
+ static nsresult SetToEmptyArray(nsDiscriminatedUnion* data);
+
+private:
+ ~nsVariant();
+
+protected:
+ nsDiscriminatedUnion mData;
+ PRBool mWritable;
+};
+
+/**
+ * Users of nsIVariant should be using the contractID and not this CID.
+ * - see NS_VARIANT_CONTRACTID in nsIVariant.idl.
+ */
+
+#define NS_VARIANT_CID \
+{ /* 0D6EA1D0-879C-11d5-90EF-0010A4E73D9A */ \
+ 0xd6ea1d0, \
+ 0x879c, \
+ 0x11d5, \
+ {0x90, 0xef, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a}}
+
+#define NS_VARIANT_CLASSNAME "Variant"
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp
new file mode 100644
index 00000000..259d0bd3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp
@@ -0,0 +1,1560 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 0)) -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsVoidArray.h"
+#include "nsQuickSort.h"
+#include "prmem.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "prbit.h"
+
+/**
+ * Grow the array by at least this many elements at a time.
+ */
+static const PRInt32 kMinGrowArrayBy = 8;
+static const PRInt32 kMaxGrowArrayBy = 1024;
+
+/**
+ * This is the threshold (in bytes) of the mImpl struct, past which
+ * we'll force the array to grow geometrically
+ */
+static const PRInt32 kLinearThreshold = 24 * sizeof(void *);
+
+/**
+ * Compute the number of bytes requires for the mImpl struct that will
+ * hold |n| elements.
+ */
+#define SIZEOF_IMPL(n_) (sizeof(Impl) + sizeof(void *) * ((n_) - 1))
+
+
+/**
+ * Compute the number of elements that an mImpl struct of |n| bytes
+ * will hold.
+ */
+#define CAPACITYOF_IMPL(n_) ((((n_) - sizeof(Impl)) / sizeof(void *)) + 1)
+
+#if DEBUG_VOIDARRAY
+#define MAXVOID 10
+
+class VoidStats {
+public:
+ VoidStats();
+ ~VoidStats();
+
+};
+
+static int sizesUsed; // number of the elements of the arrays used
+static int sizesAlloced[MAXVOID]; // sizes of the allocations. sorted
+static int NumberOfSize[MAXVOID]; // number of this allocation size (1 per array)
+static int AllocedOfSize[MAXVOID]; // number of this allocation size (each size for array used)
+static int MaxAuto[MAXVOID]; // AutoArrays that maxed out at this size
+static int GrowInPlace[MAXVOID]; // arrays this size that grew in-place via realloc
+
+// these are per-allocation
+static int MaxElements[2000]; // # of arrays that maxed out at each size.
+
+// statistics macros
+#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])++; break; } \
+ } \
+ if (i >= sizesUsed && sizesUsed < MAXVOID) \
+ { sizesAlloced[sizesUsed] = (size); \
+ ((x)[sizesUsed++])++; break; \
+ } \
+ } while (0)
+
+#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])--; break; } \
+ } \
+ } while (0)
+
+
+VoidStats::VoidStats()
+{
+ sizesUsed = 1;
+ sizesAlloced[0] = 0;
+}
+
+VoidStats::~VoidStats()
+{
+ int i;
+ for (i = 0; i < sizesUsed; i++)
+ {
+ printf("Size %d:\n",sizesAlloced[i]);
+ printf("\tNumber of VoidArrays this size (max): %d\n",NumberOfSize[i]-MaxAuto[i]);
+ printf("\tNumber of AutoVoidArrays this size (max): %d\n",MaxAuto[i]);
+ printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
+ printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
+ }
+ printf("Max Size of VoidArray:\n");
+ for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
+ {
+ if (MaxElements[i])
+ printf("\t%d: %d\n",i,MaxElements[i]);
+ }
+}
+
+// Just so constructor/destructor's get called
+VoidStats gVoidStats;
+#endif
+
+inline void
+nsVoidArray::SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner)
+{
+ // old mImpl has been realloced and so we don't free/delete it
+ NS_PRECONDITION(newImpl, "can't set size");
+ mImpl = newImpl;
+ mImpl->mCount = aCount;
+ mImpl->mBits = PRUint32(aSize & kArraySizeMask) |
+ (owner ? kArrayOwnerMask : 0);
+}
+
+// This does all allocation/reallocation of the array.
+// It also will compact down to N - good for things that might grow a lot
+// at times, but usually are smaller, like JS deferred GC releases.
+PRBool nsVoidArray::SizeTo(PRInt32 aSize)
+{
+ PRUint32 oldsize = GetArraySize();
+
+ if (aSize == (PRInt32) oldsize)
+ return PR_TRUE; // no change
+
+ if (aSize <= 0)
+ {
+ // free the array if allocated
+ if (mImpl)
+ {
+ if (IsArrayOwner())
+ {
+ PR_Free(NS_REINTERPRET_CAST(char *, mImpl));
+ mImpl = nsnull;
+ }
+ else
+ {
+ mImpl->mCount = 0; // nsAutoVoidArray
+ }
+ }
+ return PR_TRUE;
+ }
+
+ if (mImpl && IsArrayOwner())
+ {
+ // We currently own an array impl. Resize it appropriately.
+ if (aSize < mImpl->mCount)
+ {
+ // XXX Note: we could also just resize to mCount
+ return PR_TRUE; // can't make it that small, ignore request
+ }
+
+ char* bytes = (char *) PR_Realloc(mImpl,SIZEOF_IMPL(aSize));
+ Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
+ if (!newImpl)
+ return PR_FALSE;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl == newImpl)
+ ADD_TO_STATS(GrowInPlace,oldsize);
+ ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
+ if (aSize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
+ if (oldsize)
+ SUB_FROM_STATS(NumberOfSize,oldsize);
+ mMaxSize = aSize;
+ if (mIsAuto)
+ {
+ ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
+ SUB_FROM_STATS(MaxAuto,oldsize);
+ }
+ }
+#endif
+ SetArray(newImpl,aSize,newImpl->mCount,PR_TRUE);
+ return PR_TRUE;
+ }
+
+ // just allocate an array
+ // allocate the exact size requested
+ char* bytes = (char *) PR_Malloc(SIZEOF_IMPL(aSize));
+ Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
+ if (!newImpl)
+ return PR_FALSE;
+
+#if DEBUG_VOIDARRAY
+ ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
+ if (aSize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
+ if (oldsize && !mImpl)
+ SUB_FROM_STATS(NumberOfSize,oldsize);
+ mMaxSize = aSize;
+ }
+#endif
+ if (mImpl)
+ {
+#if DEBUG_VOIDARRAY
+ ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
+ SUB_FROM_STATS(MaxAuto,0);
+ SUB_FROM_STATS(NumberOfSize,0);
+ mIsAuto = PR_TRUE;
+#endif
+ // We must be growing an nsAutoVoidArray - copy since we didn't
+ // realloc.
+ memcpy(newImpl->mArray, mImpl->mArray,
+ mImpl->mCount * sizeof(mImpl->mArray[0]));
+ }
+
+ SetArray(newImpl,aSize,mImpl ? mImpl->mCount : 0,PR_TRUE);
+ // no memset; handled later in ReplaceElementAt if needed
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::GrowArrayBy(PRInt32 aGrowBy)
+{
+ // We have to grow the array. Grow by kMinGrowArrayBy slots if we're
+ // smaller than kLinearThreshold bytes, or a power of two if we're
+ // larger. This is much more efficient with most memory allocators,
+ // especially if it's very large, or of the allocator is binned.
+ if (aGrowBy < kMinGrowArrayBy)
+ aGrowBy = kMinGrowArrayBy;
+
+ PRUint32 newCapacity = GetArraySize() + aGrowBy; // Minimum increase
+ PRUint32 newSize = SIZEOF_IMPL(newCapacity);
+
+ if (newSize >= (PRUint32) kLinearThreshold)
+ {
+ // newCount includes enough space for at least kMinGrowArrayBy new
+ // slots. Select the next power-of-two size in bytes above or
+ // equal to that.
+ // Also, limit the increase in size to about a VM page or two.
+ if (GetArraySize() >= kMaxGrowArrayBy)
+ {
+ newCapacity = GetArraySize() + PR_MAX(kMaxGrowArrayBy,aGrowBy);
+ newSize = SIZEOF_IMPL(newCapacity);
+ }
+ else
+ {
+ newSize = PR_BIT(PR_CeilingLog2(newSize));
+ newCapacity = CAPACITYOF_IMPL(newSize);
+ }
+ }
+ // frees old mImpl IF this succeeds
+ if (!SizeTo(newCapacity))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+nsVoidArray::nsVoidArray()
+ : mImpl(nsnull)
+{
+ MOZ_COUNT_CTOR(nsVoidArray);
+#if DEBUG_VOIDARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ mIsAuto = PR_FALSE;
+ ADD_TO_STATS(NumberOfSize,0);
+ MaxElements[0]++;
+#endif
+}
+
+nsVoidArray::nsVoidArray(PRInt32 aCount)
+ : mImpl(nsnull)
+{
+ MOZ_COUNT_CTOR(nsVoidArray);
+#if DEBUG_VOIDARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ mIsAuto = PR_FALSE;
+ MaxElements[0]++;
+#endif
+ SizeTo(aCount);
+}
+
+nsVoidArray& nsVoidArray::operator=(const nsVoidArray& other)
+{
+ PRInt32 otherCount = other.Count();
+ PRInt32 maxCount = GetArraySize();
+ if (otherCount)
+ {
+ if (otherCount > maxCount)
+ {
+ // frees old mImpl IF this succeeds
+ if (!GrowArrayBy(otherCount-maxCount))
+ return *this; // XXX The allocation failed - don't do anything
+
+ memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
+ mImpl->mCount = otherCount;
+ }
+ else
+ {
+ // the old array can hold the new array
+ memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
+ mImpl->mCount = otherCount;
+ // if it shrank a lot, compact it anyways
+ if ((otherCount*2) < maxCount && maxCount > 100)
+ {
+ Compact(); // shrank by at least 50 entries
+ }
+ }
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+ }
+ else
+ {
+ if (mImpl && IsArrayOwner())
+ PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
+
+ mImpl = nsnull;
+ }
+
+ return *this;
+}
+
+nsVoidArray::~nsVoidArray()
+{
+ MOZ_COUNT_DTOR(nsVoidArray);
+ if (mImpl && IsArrayOwner())
+ PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
+}
+
+PRInt32 nsVoidArray::IndexOf(void* aPossibleElement) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ if (*ap == aPossibleElement)
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool nsVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
+{
+ PRInt32 oldCount = Count();
+ NS_ASSERTION(aIndex >= 0,"InsertElementAt(negative index)");
+ if (PRUint32(aIndex) > PRUint32(oldCount))
+ {
+ // An invalid index causes the insertion to fail
+ // Invalid indexes are ones that add more than one entry to the
+ // array (i.e., they can append).
+ return PR_FALSE;
+ }
+
+ if (oldCount >= GetArraySize())
+ {
+ if (!GrowArrayBy(1))
+ return PR_FALSE;
+ }
+ // else the array is already large enough
+
+ PRInt32 slide = oldCount - aIndex;
+ if (0 != slide)
+ {
+ // Slide data over to make room for the insertion
+ memmove(mImpl->mArray + aIndex + 1, mImpl->mArray + aIndex,
+ slide * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mArray[aIndex] = aElement;
+ mImpl->mCount++;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::InsertElementsAt(const nsVoidArray& other, PRInt32 aIndex)
+{
+ PRInt32 oldCount = Count();
+ PRInt32 otherCount = other.Count();
+
+ NS_ASSERTION(aIndex >= 0,"InsertElementsAt(negative index)");
+ if (PRUint32(aIndex) > PRUint32(oldCount))
+ {
+ // An invalid index causes the insertion to fail
+ // Invalid indexes are ones that are more than one entry past the end of
+ // the array (i.e., they can append).
+ return PR_FALSE;
+ }
+
+ if (oldCount + otherCount > GetArraySize())
+ {
+ if (!GrowArrayBy(otherCount))
+ return PR_FALSE;;
+ }
+ // else the array is already large enough
+
+ PRInt32 slide = oldCount - aIndex;
+ if (0 != slide)
+ {
+ // Slide data over to make room for the insertion
+ memmove(mImpl->mArray + aIndex + otherCount, mImpl->mArray + aIndex,
+ slide * sizeof(mImpl->mArray[0]));
+ }
+
+ for (PRInt32 i = 0; i < otherCount; i++)
+ {
+ // copy all the elements (destroys aIndex)
+ mImpl->mArray[aIndex++] = other.mImpl->mArray[i];
+ mImpl->mCount++;
+ }
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
+{
+ NS_ASSERTION(aIndex >= 0,"ReplaceElementAt(negative index)");
+ if (aIndex < 0)
+ return PR_FALSE;
+
+ // Unlike InsertElementAt, ReplaceElementAt can implicitly add more
+ // than just the one element to the array.
+ if (PRUint32(aIndex) >= PRUint32(GetArraySize()))
+ {
+ PRInt32 oldCount = Count();
+ PRInt32 requestedCount = aIndex + 1;
+ PRInt32 growDelta = requestedCount - oldCount;
+
+ // frees old mImpl IF this succeeds
+ if (!GrowArrayBy(growDelta))
+ return PR_FALSE;
+ }
+
+ mImpl->mArray[aIndex] = aElement;
+ if (aIndex >= mImpl->mCount)
+ {
+ // Make sure that any entries implicitly added to the array by this
+ // ReplaceElementAt are cleared to 0. Some users of this assume that.
+ // This code means we don't have to memset when we allocate an array.
+ if (aIndex > mImpl->mCount) // note: not >=
+ {
+ // For example, if mCount is 2, and we do a ReplaceElementAt for
+ // element[5], then we need to set three entries ([2], [3], and [4])
+ // to 0.
+ memset(&mImpl->mArray[mImpl->mCount], 0,
+ (aIndex - mImpl->mCount) * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mCount = aIndex + 1;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+ }
+
+ return PR_TRUE;
+}
+
+// useful for doing LRU arrays
+PRBool nsVoidArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
+{
+ void *tempElement;
+
+ if (aTo == aFrom)
+ return PR_TRUE;
+
+ NS_ASSERTION(aTo >= 0 && aFrom >= 0,"MoveElement(negative index)");
+ if (aTo >= Count() || aFrom >= Count())
+ {
+ // can't extend the array when moving an element. Also catches mImpl = null
+ return PR_FALSE;
+ }
+ tempElement = mImpl->mArray[aFrom];
+
+ if (aTo < aFrom)
+ {
+ // Moving one element closer to the head; the elements inbetween move down
+ memmove(mImpl->mArray + aTo + 1, mImpl->mArray + aTo,
+ (aFrom-aTo) * sizeof(mImpl->mArray[0]));
+ mImpl->mArray[aTo] = tempElement;
+ }
+ else // already handled aFrom == aTo
+ {
+ // Moving one element closer to the tail; the elements inbetween move up
+ memmove(mImpl->mArray + aFrom, mImpl->mArray + aFrom + 1,
+ (aTo-aFrom) * sizeof(mImpl->mArray[0]));
+ mImpl->mArray[aTo] = tempElement;
+ }
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
+{
+ PRInt32 oldCount = Count();
+ NS_ASSERTION(aIndex >= 0,"RemoveElementsAt(negative index)");
+ if (PRUint32(aIndex) >= PRUint32(oldCount))
+ {
+ // An invalid index causes the replace to fail
+ return PR_FALSE;
+ }
+ // Limit to available entries starting at aIndex
+ if (aCount + aIndex > oldCount)
+ aCount = oldCount - aIndex;
+
+ // We don't need to move any elements if we're removing the
+ // last element in the array
+ if (aIndex < (oldCount - aCount))
+ {
+ memmove(mImpl->mArray + aIndex, mImpl->mArray + aIndex + aCount,
+ (oldCount - (aIndex + aCount)) * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mCount -= aCount;
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::RemoveElement(void* aElement)
+{
+ PRInt32 theIndex = IndexOf(aElement);
+ if (theIndex != -1)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+void nsVoidArray::Clear()
+{
+ if (mImpl)
+ {
+ mImpl->mCount = 0;
+ }
+}
+
+void nsVoidArray::Compact()
+{
+ if (mImpl)
+ {
+ // XXX NOTE: this is quite inefficient in many cases if we're only
+ // compacting by a little, but some callers care more about memory use.
+ if (GetArraySize() > Count())
+ {
+ SizeTo(Count());
+ }
+ }
+}
+
+// Needed because we want to pass the pointer to the item in the array
+// to the comparator function, not a pointer to the pointer in the array.
+struct VoidArrayComparatorContext {
+ nsVoidArrayComparatorFunc mComparatorFunc;
+ void* mData;
+};
+
+PR_STATIC_CALLBACK(int)
+VoidArrayComparator(const void* aElement1, const void* aElement2, void* aData)
+{
+ VoidArrayComparatorContext* ctx = NS_STATIC_CAST(VoidArrayComparatorContext*, aData);
+ return (*ctx->mComparatorFunc)(*NS_STATIC_CAST(void* const*, aElement1),
+ *NS_STATIC_CAST(void* const*, aElement2),
+ ctx->mData);
+}
+
+void nsVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
+{
+ if (mImpl && mImpl->mCount > 1)
+ {
+ VoidArrayComparatorContext ctx = {aFunc, aData};
+ NS_QuickSort(mImpl->mArray, mImpl->mCount, sizeof(mImpl->mArray[0]),
+ VoidArrayComparator, &ctx);
+ }
+}
+
+PRBool nsVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = -1;
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(mImpl->mArray[index], aData);
+ }
+ }
+ return running;
+}
+
+PRBool nsVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = Count();
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(mImpl->mArray[index], aData);
+ }
+ }
+ return running;
+}
+
+//----------------------------------------------------------------
+// nsAutoVoidArray
+
+nsAutoVoidArray::nsAutoVoidArray()
+ : nsVoidArray()
+{
+ // Don't need to clear it. Some users just call ReplaceElementAt(),
+ // but we'll clear it at that time if needed to save CPU cycles.
+#if DEBUG_VOIDARRAY
+ mIsAuto = PR_TRUE;
+ ADD_TO_STATS(MaxAuto,0);
+#endif
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+}
+
+void nsAutoVoidArray::Clear()
+{
+ // We don't have to free on Clear, but since we have a built-in buffer,
+ // it's worth considering.
+ nsVoidArray::Clear();
+ if (IsArrayOwner() && GetArraySize() > 4*kAutoBufSize)
+ SizeTo(0); // we override CompactTo - delete and repoint at auto array
+}
+
+PRBool nsAutoVoidArray::SizeTo(PRInt32 aSize)
+{
+ if (!nsVoidArray::SizeTo(aSize))
+ return PR_FALSE;
+
+ if (!mImpl)
+ {
+ // reset the array to point to our autobuf
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+ }
+ return PR_TRUE;
+}
+
+void nsAutoVoidArray::Compact()
+{
+ nsVoidArray::Compact();
+ if (!mImpl)
+ {
+ // reset the array to point to our autobuf
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+ }
+}
+
+//----------------------------------------------------------------
+// nsStringArray
+
+nsStringArray::nsStringArray(void)
+ : nsVoidArray()
+{
+}
+
+nsStringArray::nsStringArray(PRInt32 aCount)
+ : nsVoidArray(aCount)
+{
+}
+
+nsStringArray::~nsStringArray(void)
+{
+ Clear();
+}
+
+nsStringArray&
+nsStringArray::operator=(const nsStringArray& other)
+{
+ // Copy the pointers
+ nsVoidArray::operator=(other);
+
+ // Now copy the strings
+ for (PRInt32 i = Count() - 1; i >= 0; --i)
+ {
+ nsString* oldString = NS_STATIC_CAST(nsString*, other.ElementAt(i));
+ mImpl->mArray[i] = new nsString(*oldString);
+ }
+
+ return *this;
+}
+
+void
+nsStringArray::StringAt(PRInt32 aIndex, nsAString& aString) const
+{
+ nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ aString.Assign(*string);
+ }
+ else
+ {
+ aString.Truncate();
+ }
+}
+
+nsString*
+nsStringArray::StringAt(PRInt32 aIndex) const
+{
+ return NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+}
+
+PRInt32
+nsStringArray::IndexOf(const nsAString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsString* string = NS_STATIC_CAST(nsString*, *ap);
+ if (string->Equals(aPossibleString))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool
+nsStringArray::InsertStringAt(const nsAString& aString, PRInt32 aIndex)
+{
+ nsString* string = new nsString(aString);
+ if (nsVoidArray::InsertElementAt(string, aIndex))
+ {
+ return PR_TRUE;
+ }
+ delete string;
+ return PR_FALSE;
+}
+
+PRBool
+nsStringArray::ReplaceStringAt(const nsAString& aString,
+ PRInt32 aIndex)
+{
+ nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ *string = aString;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsStringArray::RemoveString(const nsAString& aString)
+{
+ PRInt32 index = IndexOf(aString);
+ if (-1 < index)
+ {
+ return RemoveStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool nsStringArray::RemoveStringAt(PRInt32 aIndex)
+{
+ nsString* string = StringAt(aIndex);
+ if (nsnull != string)
+ {
+ nsVoidArray::RemoveElementAt(aIndex);
+ delete string;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+void
+nsStringArray::Clear(void)
+{
+ PRInt32 index = Count();
+ while (0 <= --index)
+ {
+ nsString* string = NS_STATIC_CAST(nsString*, mImpl->mArray[index]);
+ delete string;
+ }
+ nsVoidArray::Clear();
+}
+
+PR_STATIC_CALLBACK(int)
+CompareString(const nsString* aString1, const nsString* aString2, void*)
+{
+ return Compare(*aString1, *aString2);
+}
+
+void nsStringArray::Sort(void)
+{
+ Sort(CompareString, nsnull);
+}
+
+void nsStringArray::Sort(nsStringArrayComparatorFunc aFunc, void* aData)
+{
+ nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
+}
+
+PRBool
+nsStringArray::EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = -1;
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+PRBool
+nsStringArray::EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = Count();
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+
+
+//----------------------------------------------------------------
+// nsCStringArray
+
+nsCStringArray::nsCStringArray(void)
+ : nsVoidArray()
+{
+}
+
+// Parses a given string using the delimiter passed in and appends items
+// parsed to the array.
+void
+nsCStringArray::ParseString(const char* string, const char* delimiter)
+{
+ if (string && *string && delimiter && *delimiter) {
+ char *newStr;
+ char *rest = nsCRT::strdup(string);
+ char *token = nsCRT::strtok(rest, delimiter, &newStr);
+
+ while (token) {
+ if (*token) {
+ /* calling AppendElement(void*) to avoid extra nsCString copy */
+ AppendElement(new nsCString(token));
+ }
+ token = nsCRT::strtok(newStr, delimiter, &newStr);
+ }
+ PR_FREEIF(rest);
+ }
+}
+
+nsCStringArray::nsCStringArray(PRInt32 aCount)
+ : nsVoidArray(aCount)
+{
+}
+
+nsCStringArray::~nsCStringArray(void)
+{
+ Clear();
+}
+
+nsCStringArray&
+nsCStringArray::operator=(const nsCStringArray& other)
+{
+ // Copy the pointers
+ nsVoidArray::operator=(other);
+
+ // Now copy the strings
+ for (PRInt32 i = Count() - 1; i >= 0; --i)
+ {
+ nsCString* oldString = NS_STATIC_CAST(nsCString*, other.ElementAt(i));
+ mImpl->mArray[i] = new nsCString(*oldString);
+ }
+
+ return *this;
+}
+
+void
+nsCStringArray::CStringAt(PRInt32 aIndex, nsACString& aCString) const
+{
+ nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ aCString = *string;
+ }
+ else
+ {
+ aCString.Truncate();
+ }
+}
+
+nsCString*
+nsCStringArray::CStringAt(PRInt32 aIndex) const
+{
+ return NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+}
+
+PRInt32
+nsCStringArray::IndexOf(const nsACString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
+ if (string->Equals(aPossibleString))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRInt32
+nsCStringArray::IndexOfIgnoreCase(const nsACString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
+ if (string->Equals(aPossibleString, nsCaseInsensitiveCStringComparator()))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool
+nsCStringArray::InsertCStringAt(const nsACString& aCString, PRInt32 aIndex)
+{
+ nsCString* string = new nsCString(aCString);
+ if (nsVoidArray::InsertElementAt(string, aIndex))
+ {
+ return PR_TRUE;
+ }
+ delete string;
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex)
+{
+ nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ *string = aCString;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::RemoveCString(const nsACString& aCString)
+{
+ PRInt32 index = IndexOf(aCString);
+ if (-1 < index)
+ {
+ return RemoveCStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::RemoveCStringIgnoreCase(const nsACString& aCString)
+{
+ PRInt32 index = IndexOfIgnoreCase(aCString);
+ if (-1 < index)
+ {
+ return RemoveCStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool nsCStringArray::RemoveCStringAt(PRInt32 aIndex)
+{
+ nsCString* string = CStringAt(aIndex);
+ if (nsnull != string)
+ {
+ nsVoidArray::RemoveElementAt(aIndex);
+ delete string;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+void
+nsCStringArray::Clear(void)
+{
+ PRInt32 index = Count();
+ while (0 <= --index)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, mImpl->mArray[index]);
+ delete string;
+ }
+ nsVoidArray::Clear();
+}
+
+PR_STATIC_CALLBACK(int)
+CompareCString(const nsCString* aCString1, const nsCString* aCString2, void*)
+{
+ return Compare(*aCString1, *aCString2);
+}
+
+PR_STATIC_CALLBACK(int)
+CompareCStringIgnoreCase(const nsCString* aCString1, const nsCString* aCString2, void*)
+{
+ return Compare(*aCString1, *aCString2, nsCaseInsensitiveCStringComparator());
+}
+
+void nsCStringArray::Sort(void)
+{
+ Sort(CompareCString, nsnull);
+}
+
+void nsCStringArray::SortIgnoreCase(void)
+{
+ Sort(CompareCStringIgnoreCase, nsnull);
+}
+
+void nsCStringArray::Sort(nsCStringArrayComparatorFunc aFunc, void* aData)
+{
+ nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
+}
+
+PRBool
+nsCStringArray::EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = -1;
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+PRBool
+nsCStringArray::EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = Count();
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+
+//----------------------------------------------------------------------
+// NOTE: nsSmallVoidArray elements MUST all have the low bit as 0.
+// This means that normally it's only used for pointers, and in particular
+// structures or objects.
+nsSmallVoidArray::nsSmallVoidArray()
+{
+ mChildren = nsnull;
+}
+
+nsSmallVoidArray::~nsSmallVoidArray()
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ delete vector;
+ }
+}
+
+nsSmallVoidArray&
+nsSmallVoidArray::operator=(nsSmallVoidArray& other)
+{
+ nsVoidArray* ourArray = GetChildVector();
+ nsVoidArray* otherArray = other.GetChildVector();
+
+ if (HasVector())
+ {
+ if (other.HasVector())
+ {
+ // if both are real arrays, just use array= */
+ *ourArray = *otherArray;
+ }
+ else
+ {
+ // we have an array, but the other doesn't.
+ otherArray = other.SwitchToVector();
+ if (otherArray)
+ *ourArray = *otherArray;
+ }
+ }
+ else
+ {
+ if (other.HasVector())
+ {
+ // we have no array, but other does
+ ourArray = SwitchToVector();
+ if (ourArray)
+ *ourArray = *otherArray;
+ }
+ else
+ {
+ // neither has an array (either may have 0 or 1 items)
+ SetSingleChild(other.GetSingleChild());
+ }
+ }
+ return *this;
+}
+
+PRInt32
+nsSmallVoidArray::GetArraySize() const
+{
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->GetArraySize();
+
+ return 1;
+}
+
+PRInt32
+nsSmallVoidArray::Count() const
+{
+ if (HasSingleChild())
+ {
+ return 1;
+ }
+ else {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->Count();
+ }
+
+ return 0;
+}
+
+void*
+nsSmallVoidArray::ElementAt(PRInt32 aIndex) const
+{
+ if (HasSingleChild())
+ {
+ if (0 == aIndex)
+ return (void*)GetSingleChild();
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->ElementAt(aIndex);
+ }
+
+ return nsnull;
+}
+
+PRInt32
+nsSmallVoidArray::IndexOf(void* aPossibleElement) const
+{
+ if (HasSingleChild())
+ {
+ if (aPossibleElement == (void*)GetSingleChild())
+ return 0;
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->IndexOf(aPossibleElement);
+ }
+
+ return -1;
+}
+
+PRBool
+nsSmallVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
+{
+ nsVoidArray* vector;
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ if (HasSingleChild())
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (!vector)
+ {
+ if (0 == aIndex)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+ }
+ }
+
+ return vector->InsertElementAt(aElement, aIndex);
+}
+
+PRBool nsSmallVoidArray::InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex)
+{
+ nsVoidArray* vector;
+ PRInt32 count = other.Count();
+ if (count == 0)
+ return PR_TRUE;
+
+#ifdef DEBUG
+ for (int i = 0; i < count; i++)
+ {
+ NS_ASSERTION(!(PtrBits(other.ElementAt(i)) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(other.ElementAt(i) != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+ }
+#endif
+
+ if (!HasVector())
+ {
+ if (HasSingleChild() || count > 1 || aIndex > 0)
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ // count == 1, aIndex == 0, no elements already
+ SetSingleChild(other[0]);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ vector = GetChildVector();
+ }
+
+ if (vector)
+ {
+ return vector->InsertElementsAt(other,aIndex);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsSmallVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
+{
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ if (HasSingleChild())
+ {
+ if (aIndex == 0)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->ReplaceElementAt(aElement, aIndex);
+
+ return PR_FALSE;
+ }
+}
+
+PRBool
+nsSmallVoidArray::AppendElement(void* aElement)
+{
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ nsVoidArray* vector;
+ if (HasSingleChild())
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (!vector)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ }
+
+ return vector->AppendElement(aElement);
+}
+
+PRBool
+nsSmallVoidArray::RemoveElement(void* aElement)
+{
+ if (HasSingleChild())
+ {
+ if (aElement == GetSingleChild())
+ {
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->RemoveElement(aElement);
+ }
+
+ return PR_FALSE;
+}
+
+PRBool
+nsSmallVoidArray::RemoveElementAt(PRInt32 aIndex)
+{
+ if (HasSingleChild())
+ {
+ if (0 == aIndex)
+ {
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ {
+ return vector->RemoveElementAt(aIndex);
+ }
+ }
+
+ return PR_FALSE;
+}
+
+PRBool
+nsSmallVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
+{
+ nsVoidArray* vector = GetChildVector();
+
+ if (aCount == 0)
+ return PR_TRUE;
+
+ if (HasSingleChild())
+ {
+ if (aIndex == 0)
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+
+ if (!vector)
+ return PR_TRUE;
+
+ // complex case; remove entries from an array
+ return vector->RemoveElementsAt(aIndex,aCount);
+}
+
+void
+nsSmallVoidArray::Clear()
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ vector->Clear();
+ }
+ else
+ {
+ SetSingleChild(nsnull);
+ }
+}
+
+PRBool
+nsSmallVoidArray::SizeTo(PRInt32 aMin)
+{
+ nsVoidArray* vector;
+ if (!HasVector())
+ {
+ if (aMin <= 1)
+ return PR_TRUE;
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (aMin <= 1)
+ {
+ void *prev = nsnull;
+ if (vector->Count() == 1)
+ {
+ prev = vector->ElementAt(0);
+ }
+ delete vector;
+ SetSingleChild(prev);
+ return PR_TRUE;
+ }
+ }
+ return vector->SizeTo(aMin);
+}
+
+void
+nsSmallVoidArray::Compact()
+{
+ if (!HasSingleChild())
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ vector->Compact();
+ }
+}
+
+void
+nsSmallVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ vector->Sort(aFunc,aData);
+ }
+}
+
+PRBool
+nsSmallVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ return vector->EnumerateForwards(aFunc,aData);
+ }
+ if (HasSingleChild())
+ {
+ return (*aFunc)(GetSingleChild(), aData);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsSmallVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ return vector->EnumerateBackwards(aFunc,aData);
+ }
+ if (HasSingleChild())
+ {
+ return (*aFunc)(GetSingleChild(), aData);
+ }
+ return PR_TRUE;
+}
+
+void
+nsSmallVoidArray::SetSingleChild(void* aChild)
+{
+ if (aChild)
+ mChildren = (void*)(PtrBits(aChild) | 0x1);
+ else
+ mChildren = nsnull;
+}
+
+nsVoidArray*
+nsSmallVoidArray::SwitchToVector()
+{
+ void* child = GetSingleChild();
+
+ mChildren = (void*)new nsAutoVoidArray();
+ nsVoidArray* vector = GetChildVector();
+ if (vector && child)
+ vector->AppendElement(child);
+
+ return vector;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h
new file mode 100644
index 00000000..28d950e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h
@@ -0,0 +1,410 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 0)) -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsVoidArray_h___
+#define nsVoidArray_h___
+
+//#define DEBUG_VOIDARRAY 1
+
+#include "nscore.h"
+#include "nsAString.h"
+
+// Comparator callback function for sorting array values.
+typedef int (* PR_CALLBACK nsVoidArrayComparatorFunc)
+ (const void* aElement1, const void* aElement2, void* aData);
+
+// Enumerator callback function. Return PR_FALSE to stop
+typedef PRBool (* PR_CALLBACK nsVoidArrayEnumFunc)(void* aElement, void *aData);
+
+/// A basic zero-based array of void*'s that manages its own memory
+class NS_COM nsVoidArray {
+public:
+ nsVoidArray();
+ nsVoidArray(PRInt32 aCount); // initial count of aCount elements set to nsnull
+ virtual ~nsVoidArray();
+
+ nsVoidArray& operator=(const nsVoidArray& other);
+
+ inline PRInt32 Count() const {
+ return mImpl ? mImpl->mCount : 0;
+ }
+ // returns the max number that can be held without allocating
+ inline PRInt32 GetArraySize() const {
+ return mImpl ? (PRInt32(mImpl->mBits) & kArraySizeMask) : 0;
+ }
+
+ void* FastElementAt(PRInt32 aIndex) const
+ {
+ NS_ASSERTION(0 <= aIndex && aIndex < Count(), "index out of range");
+ return mImpl->mArray[aIndex];
+ }
+
+ // This both asserts and bounds-checks, because (1) we don't want
+ // people to write bad code, but (2) we don't want to change it to
+ // crashing for backwards compatibility. See bug 96108.
+ void* ElementAt(PRInt32 aIndex) const
+ {
+ NS_ASSERTION(0 <= aIndex && aIndex < Count(), "index out of range");
+ return SafeElementAt(aIndex);
+ }
+
+ // bounds-checked version
+ void* SafeElementAt(PRInt32 aIndex) const
+ {
+ if (PRUint32(aIndex) >= PRUint32(Count())) // handles aIndex < 0 too
+ {
+ return nsnull;
+ }
+ // The bounds check ensures mImpl is non-null.
+ return mImpl->mArray[aIndex];
+ }
+
+ void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
+
+ PRInt32 IndexOf(void* aPossibleElement) const;
+
+ PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
+ PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
+
+ PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
+
+ // useful for doing LRU arrays, sorting, etc
+ PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
+
+ PRBool AppendElement(void* aElement) {
+ return InsertElementAt(aElement, Count());
+ }
+
+ PRBool AppendElements(nsVoidArray& aElements) {
+ return InsertElementsAt(aElements, Count());
+ }
+
+ PRBool RemoveElement(void* aElement);
+ PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
+ PRBool RemoveElementAt(PRInt32 aIndex) { return RemoveElementsAt(aIndex,1); }
+
+ virtual void Clear();
+
+ virtual PRBool SizeTo(PRInt32 aMin);
+ // Subtly different - Compact() tries to be smart about whether we
+ // should reallocate the array; SizeTo() just does it.
+ virtual void Compact();
+
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
+
+protected:
+ virtual PRBool GrowArrayBy(PRInt32 aGrowBy);
+
+ struct Impl {
+ /**
+ * Packed bits. The low 31 bits are the array's size.
+ * The highest bit is a flag that indicates
+ * whether or not we "own" mArray, and must free() it when
+ * destroyed.
+ */
+ PRUint32 mBits;
+
+ /**
+ * The number of elements in the array
+ */
+ PRInt32 mCount;
+
+ /**
+ * Array data, padded out to the actual size of the array.
+ */
+ void* mArray[1];
+ };
+
+ Impl* mImpl;
+#if DEBUG_VOIDARRAY
+ PRInt32 mMaxCount;
+ PRInt32 mMaxSize;
+ PRBool mIsAuto;
+#endif
+
+ enum {
+ kArrayOwnerMask = 1 << 31,
+ kArraySizeMask = ~kArrayOwnerMask
+ };
+
+
+ // bit twiddlers
+ void SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner);
+ inline PRBool IsArrayOwner() const {
+ return mImpl ? (PRBool(mImpl->mBits) & kArrayOwnerMask) : PR_FALSE;
+ }
+
+private:
+ /// Copy constructors are not allowed
+ nsVoidArray(const nsVoidArray& other);
+};
+
+
+// A zero-based array with a bit of automatic internal storage
+class NS_COM nsAutoVoidArray : public nsVoidArray {
+public:
+ nsAutoVoidArray();
+ void Clear();
+
+ virtual PRBool SizeTo(PRInt32 aMin);
+ virtual void Compact();
+
+protected:
+ // The internal storage
+ enum { kAutoBufSize = 8 };
+ char mAutoBuf[sizeof(Impl) + (kAutoBufSize - 1) * sizeof(void*)];
+};
+
+
+class nsString;
+
+typedef int (* PR_CALLBACK nsStringArrayComparatorFunc)
+ (const nsString* aElement1, const nsString* aElement2, void* aData);
+
+typedef PRBool (*nsStringArrayEnumFunc)(nsString& aElement, void *aData);
+
+class NS_COM nsStringArray: protected nsVoidArray
+{
+public:
+ nsStringArray(void);
+ nsStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
+ virtual ~nsStringArray(void);
+
+ nsStringArray& operator=(const nsStringArray& other);
+
+ PRInt32 Count(void) const {
+ return nsVoidArray::Count();
+ }
+
+ void StringAt(PRInt32 aIndex, nsAString& aString) const;
+ nsString* StringAt(PRInt32 aIndex) const;
+ nsString* operator[](PRInt32 aIndex) const { return StringAt(aIndex); }
+
+ PRInt32 IndexOf(const nsAString& aPossibleString) const;
+
+ PRBool InsertStringAt(const nsAString& aString, PRInt32 aIndex);
+
+ PRBool ReplaceStringAt(const nsAString& aString, PRInt32 aIndex);
+
+ PRBool AppendString(const nsAString& aString) {
+ return InsertStringAt(aString, Count());
+ }
+
+ PRBool RemoveString(const nsAString& aString);
+ PRBool RemoveStringAt(PRInt32 aIndex);
+ void Clear(void);
+
+ void Compact(void) {
+ nsVoidArray::Compact();
+ }
+
+ void Sort(void);
+ void Sort(nsStringArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData);
+
+private:
+ /// Copy constructors are not allowed
+ nsStringArray(const nsStringArray& other);
+};
+
+
+class nsCString;
+
+typedef int (* PR_CALLBACK nsCStringArrayComparatorFunc)
+ (const nsCString* aElement1, const nsCString* aElement2, void* aData);
+
+typedef PRBool (*nsCStringArrayEnumFunc)(nsCString& aElement, void *aData);
+
+class NS_COM nsCStringArray: protected nsVoidArray
+{
+public:
+ nsCStringArray(void);
+ nsCStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
+ virtual ~nsCStringArray(void);
+
+ nsCStringArray& operator=(const nsCStringArray& other);
+
+ // Parses a given string using the delimiter passed in. If the array
+ // already has some elements, items parsed from string will be appended
+ // to array. For example, array.ParseString("a,b,c", ","); will add strings
+ // "a", "b" and "c" to the array. Parsing process has the same tokenizing
+ // behavior as strtok().
+ void ParseString(const char* string, const char* delimiter);
+
+ PRInt32 Count(void) const {
+ return nsVoidArray::Count();
+ }
+
+ void CStringAt(PRInt32 aIndex, nsACString& aCString) const;
+ nsCString* CStringAt(PRInt32 aIndex) const;
+ nsCString* operator[](PRInt32 aIndex) const { return CStringAt(aIndex); }
+
+ PRInt32 IndexOf(const nsACString& aPossibleString) const;
+ PRInt32 IndexOfIgnoreCase(const nsACString& aPossibleString) const;
+
+ PRBool InsertCStringAt(const nsACString& aCString, PRInt32 aIndex);
+
+ PRBool ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex);
+
+ PRBool AppendCString(const nsACString& aCString) {
+ return InsertCStringAt(aCString, Count());
+ }
+
+ PRBool RemoveCString(const nsACString& aCString);
+ PRBool RemoveCStringIgnoreCase(const nsACString& aCString);
+ PRBool RemoveCStringAt(PRInt32 aIndex);
+ void Clear(void);
+
+ void Compact(void) {
+ nsVoidArray::Compact();
+ }
+
+ void Sort(void);
+ void SortIgnoreCase(void);
+ void Sort(nsCStringArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData);
+
+private:
+ /// Copy constructors are not allowed
+ nsCStringArray(const nsCStringArray& other);
+};
+
+
+//===================================================================
+// nsSmallVoidArray is not a general-purpose replacement for
+// ns(Auto)VoidArray because there is (some) extra CPU overhead for arrays
+// larger than 1 element, though not a lot. It is appropriate for
+// space-sensitive uses where sizes of 0 or 1 are moderately common or
+// more, and where we're NOT storing arbitrary integers or arbitrary
+// pointers.
+
+// NOTE: nsSmallVoidArray can ONLY be used for holding items that always
+// have the low bit as a 0 - i.e. element & 1 == 0. This happens to be
+// true for allocated and object pointers for all the architectures we run
+// on, but conceivably there might be some architectures/compilers for
+// which it is NOT true. We know this works for all existing architectures
+// because if it didn't then nsCheapVoidArray would have failed. Also note
+// that we will ASSERT if this assumption is violated in DEBUG builds.
+
+// XXX we're really re-implementing the whole nsVoidArray interface here -
+// some form of abstract class would be useful
+
+// I disagree on the abstraction here. If the point of this class is to be
+// as small as possible, and no one will ever derive from it, as I found
+// today, there should not be any virtualness to it to avoid the vtable
+// ptr overhead.
+
+class NS_COM nsSmallVoidArray
+{
+public:
+ nsSmallVoidArray();
+ ~nsSmallVoidArray();
+
+ nsSmallVoidArray& operator=(nsSmallVoidArray& other);
+ void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
+
+ PRInt32 GetArraySize() const;
+
+ PRInt32 Count() const;
+ void* ElementAt(PRInt32 aIndex) const;
+ void* SafeElementAt(PRInt32 aIndex) const {
+ // let compiler inline; it may be able to remove these checks
+ if (aIndex < 0 || aIndex >= Count())
+ return nsnull;
+ return ElementAt(aIndex);
+ }
+ PRInt32 IndexOf(void* aPossibleElement) const;
+ PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
+ PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
+ PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
+ PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
+ PRBool AppendElement(void* aElement);
+ PRBool AppendElements(nsVoidArray& aElements) {
+ return InsertElementsAt(aElements, Count());
+ }
+ PRBool RemoveElement(void* aElement);
+ PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
+ PRBool RemoveElementAt(PRInt32 aIndex);
+
+ void Clear();
+ PRBool SizeTo(PRInt32 aMin);
+ void Compact();
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
+
+private:
+#ifdef RT_OS_OS2 /* shut up a million warnings */
+ typedef PRUint32 PtrBits;
+#else
+ typedef PRUint64 PtrBits;
+#endif
+
+ PRBool HasSingleChild() const
+ {
+ return (mChildren && (PtrBits(mChildren) & 0x1));
+ }
+ PRBool HasVector() const
+ {
+ return (mChildren && !(PtrBits(mChildren) & 0x1));
+ }
+ void* GetSingleChild() const
+ {
+ return (mChildren ? ((void*)(PtrBits(mChildren) & ~0x1)) : nsnull);
+ }
+ void SetSingleChild(void *aChild);
+ nsVoidArray* GetChildVector() const
+ {
+ return (nsVoidArray*)mChildren;
+ }
+ nsVoidArray* SwitchToVector();
+
+ // A tagged pointer that's either a pointer to a single child
+ // or a pointer to a vector of multiple children. This is a space
+ // optimization since a large number of containers have only a
+ // single child.
+ void *mChildren;
+};
+
+#endif /* nsVoidArray_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/pldhash.c b/src/libs/xpcom18a4/xpcom/ds/pldhash.c
new file mode 100644
index 00000000..74f8cd0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/pldhash.c
@@ -0,0 +1,826 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ * Chris Waterson <waterson@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Double hashing implementation.
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "prbit.h"
+#include "pldhash.h"
+#include "prlog.h" /* for PR_ASSERT */
+
+#ifdef PL_DHASHMETER
+# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
+# include "nsTraceMalloc.h"
+# endif
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+PR_IMPLEMENT(void *)
+PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ return RTMemAlloc(nbytes);
+#else
+ return malloc(nbytes);
+#endif
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFreeTable(PLDHashTable *table, void *ptr)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+PR_IMPLEMENT(PLDHashNumber)
+PL_DHashStringKey(PLDHashTable *table, const void *key)
+{
+ PLDHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = key; *s != '\0'; s++)
+ h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ *s;
+ return h;
+}
+
+PR_IMPLEMENT(const void *)
+PL_DHashGetKeyStub(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ PLDHashEntryStub *stub = (PLDHashEntryStub *)entry;
+
+ return stub->key;
+}
+
+PR_IMPLEMENT(PLDHashNumber)
+PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key)
+{
+ return (PLDHashNumber)(uintptr_t)key >> 2;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashMatchEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+ return stub->key == key;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashMatchStringKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+ /* XXX tolerate null keys on account of sloppy Mozilla callers. */
+ return stub->key == key ||
+ (stub->key && key && strcmp(stub->key, key) == 0);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashMoveEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to)
+{
+ memcpy(to, from, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ memset(entry, 0, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree((void *) stub->key);
+#else
+ free((void *) stub->key);
+#endif
+ memset(entry, 0, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFinalizeStub(PLDHashTable *table)
+{
+}
+
+static const PLDHashTableOps stub_ops = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashVoidPtrKeyStub,
+ PL_DHashMatchEntryStub,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+PR_IMPLEMENT(const PLDHashTableOps *)
+PL_DHashGetStubOps(void)
+{
+ return &stub_ops;
+}
+
+PR_IMPLEMENT(PLDHashTable *)
+PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize,
+ PRUint32 capacity)
+{
+ PLDHashTable *table;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ table = (PLDHashTable *) RTMemAlloc(sizeof *table);
+#else
+ table = (PLDHashTable *) malloc(sizeof *table);
+#endif
+ if (!table)
+ return NULL;
+ if (!PL_DHashTableInit(table, ops, data, entrySize, capacity)) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(table);
+#else
+ free(table);
+#endif
+ return NULL;
+ }
+ return table;
+}
+
+PR_IMPLEMENT(void)
+PL_DHashTableDestroy(PLDHashTable *table)
+{
+ PL_DHashTableFinish(table);
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(table);
+#else
+ free(table);
+#endif
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+ PRUint32 entrySize, PRUint32 capacity)
+{
+ int log2;
+ PRUint32 nbytes;
+
+#ifdef DEBUG
+ if (entrySize > 10 * sizeof(void *)) {
+ fprintf(stderr,
+ "pldhash: for the table at address %p, the given entrySize"
+ " of %lu %s favors chaining over double hashing.\n",
+ (void *)table,
+ (unsigned long) entrySize,
+ (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably");
+ }
+#endif
+
+ table->ops = ops;
+ table->data = data;
+ if (capacity < PL_DHASH_MIN_SIZE)
+ capacity = PL_DHASH_MIN_SIZE;
+ log2 = PR_CeilingLog2(capacity);
+ capacity = PR_BIT(log2);
+ if (capacity >= PL_DHASH_SIZE_LIMIT)
+ return PR_FALSE;
+ table->hashShift = PL_DHASH_BITS - log2;
+ table->maxAlphaFrac = 0xC0; /* .75 */
+ table->minAlphaFrac = 0x40; /* .25 */
+ table->entrySize = entrySize;
+ table->entryCount = table->removedCount = 0;
+ table->generation = 0;
+ nbytes = capacity * entrySize;
+
+ table->entryStore = ops->allocTable(table, nbytes);
+ if (!table->entryStore)
+ return PR_FALSE;
+ memset(table->entryStore, 0, nbytes);
+ METER(memset(&table->stats, 0, sizeof table->stats));
+ return PR_TRUE;
+}
+
+/*
+ * Compute max and min load numbers (entry counts) from table params.
+ */
+#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8)
+#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8)
+
+PR_IMPLEMENT(void)
+PL_DHashTableSetAlphaBounds(PLDHashTable *table,
+ float maxAlpha,
+ float minAlpha)
+{
+ PRUint32 size;
+
+ /*
+ * Reject obviously insane bounds, rather than trying to guess what the
+ * buggy caller intended.
+ */
+ PR_ASSERT(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha);
+ if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0)
+ return;
+
+ /*
+ * Ensure that at least one entry will always be free. If maxAlpha at
+ * minimum size leaves no entries free, reduce maxAlpha based on minimum
+ * size and the precision limit of maxAlphaFrac's fixed point format.
+ */
+ PR_ASSERT(PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1);
+ if (PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) < 1) {
+ maxAlpha = (float)
+ (PL_DHASH_MIN_SIZE - PR_MAX(PL_DHASH_MIN_SIZE / 256, 1))
+ / PL_DHASH_MIN_SIZE;
+ }
+
+ /*
+ * Ensure that minAlpha is strictly less than half maxAlpha. Take care
+ * not to truncate an entry's worth of alpha when storing in minAlphaFrac
+ * (8-bit fixed point format).
+ */
+ PR_ASSERT(minAlpha < maxAlpha / 2);
+ if (minAlpha >= maxAlpha / 2) {
+ size = PL_DHASH_TABLE_SIZE(table);
+ minAlpha = (size * maxAlpha - PR_MAX(size / 256, 1)) / (2 * size);
+ }
+
+ table->maxAlphaFrac = (uint8)(maxAlpha * 256);
+ table->minAlphaFrac = (uint8)(minAlpha * 256);
+}
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd.
+ */
+#define HASH1(hash0, shift) ((hash0) >> (shift))
+#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+/*
+ * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note
+ * that a removed-entry sentinel need be stored only if the removed entry had
+ * a colliding entry added after it. Therefore we can use 1 as the collision
+ * flag in addition to the removed-entry sentinel value. Multiplicative hash
+ * uses the high order bits of keyHash, so this least-significant reservation
+ * should not hurt the hash function's effectiveness much.
+ *
+ * If you change any of these magic numbers, also update PL_DHASH_ENTRY_IS_LIVE
+ * in pldhash.h. It used to be private to pldhash.c, but then became public to
+ * assist iterator writers who inspect table->entryStore directly.
+ */
+#define COLLISION_FLAG ((PLDHashNumber) 1)
+#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0)
+#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1)
+#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1)
+#define ENTRY_IS_LIVE(entry) PL_DHASH_ENTRY_IS_LIVE(entry)
+#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0
+
+/* Match an entry's keyHash against an unstored one computed from a key. */
+#define MATCH_ENTRY_KEYHASH(entry,hash0) \
+ (((entry)->keyHash & ~COLLISION_FLAG) == (hash0))
+
+/* Compute the address of the indexed entry in table. */
+#define ADDRESS_ENTRY(table, index) \
+ ((PLDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize))
+
+PR_IMPLEMENT(void)
+PL_DHashTableFinish(PLDHashTable *table)
+{
+ char *entryAddr, *entryLimit;
+ PRUint32 entrySize;
+ PLDHashEntryHdr *entry;
+
+#ifdef DEBUG_XXXbrendan
+ static FILE *dumpfp = NULL;
+ if (!dumpfp) dumpfp = fopen("/tmp/pldhash.bigdump", "w");
+ if (dumpfp) {
+#ifdef MOZILLA_CLIENT
+ NS_TraceStack(1, dumpfp);
+#endif
+ PL_DHashTableDumpMeter(table, NULL, dumpfp);
+ fputc('\n', dumpfp);
+ }
+#endif
+
+ /* Call finalize before clearing entries, so it can enumerate them. */
+ table->ops->finalize(table);
+
+ /* Clear any remaining live entries. */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ entryLimit = entryAddr + PL_DHASH_TABLE_SIZE(table) * entrySize;
+ while (entryAddr < entryLimit) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ METER(table->stats.removeEnums++);
+ table->ops->clearEntry(table, entry);
+ }
+ entryAddr += entrySize;
+ }
+
+ /* Free entry storage last. */
+ table->ops->freeTable(table, table->entryStore);
+}
+
+static PLDHashEntryHdr * PL_DHASH_FASTCALL
+SearchTable(PLDHashTable *table, const void *key, PLDHashNumber keyHash,
+ PLDHashOperator op)
+{
+ PLDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ PLDHashEntryHdr *entry, *firstRemoved;
+ PLDHashMatchEntry matchEntry;
+ PRUint32 sizeMask;
+
+ METER(table->stats.searches++);
+ PR_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Hit: return entry. */
+ matchEntry = table->ops->matchEntry;
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = PL_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = PR_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so PL_DHASH_ADD can recycle it. */
+ if (ENTRY_IS_REMOVED(entry)) {
+ firstRemoved = entry;
+ } else {
+ firstRemoved = NULL;
+ if (op == PL_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+
+ for (;;) {
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return (firstRemoved && op == PL_DHASH_ADD) ? firstRemoved : entry;
+ }
+
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) &&
+ matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ if (ENTRY_IS_REMOVED(entry)) {
+ if (!firstRemoved)
+ firstRemoved = entry;
+ } else {
+ if (op == PL_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static PRBool
+ChangeTable(PLDHashTable *table, int deltaLog2)
+{
+ int oldLog2, newLog2;
+ PRUint32 oldCapacity, newCapacity;
+ char *newEntryStore, *oldEntryStore, *oldEntryAddr;
+ PRUint32 entrySize, i, nbytes;
+ PLDHashEntryHdr *oldEntry, *newEntry;
+ PLDHashGetKey getKey;
+ PLDHashMoveEntry moveEntry;
+
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PR_ASSERT(table->generation != PR_UINT32_MAX);
+ if (table->generation == PR_UINT32_MAX)
+ return PR_FALSE;
+#endif
+
+ /* Look, but don't touch, until we succeed in getting new entry store. */
+ oldLog2 = PL_DHASH_BITS - table->hashShift;
+ newLog2 = oldLog2 + deltaLog2;
+ oldCapacity = PR_BIT(oldLog2);
+ newCapacity = PR_BIT(newLog2);
+ if (newCapacity >= PL_DHASH_SIZE_LIMIT)
+ return PR_FALSE;
+ entrySize = table->entrySize;
+ nbytes = newCapacity * entrySize;
+
+ newEntryStore = table->ops->allocTable(table, nbytes);
+ if (!newEntryStore)
+ return PR_FALSE;
+
+ /* We can't fail from here on, so update table parameters. */
+ table->hashShift = PL_DHASH_BITS - newLog2;
+ table->removedCount = 0;
+ table->generation++;
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ if (table->generation == PR_UINT32_MAX)
+ table->generation++;
+#endif
+
+ /* Assign the new entry store to table. */
+ memset(newEntryStore, 0, nbytes);
+ oldEntryAddr = oldEntryStore = table->entryStore;
+ table->entryStore = newEntryStore;
+ getKey = table->ops->getKey;
+ moveEntry = table->ops->moveEntry;
+
+ /* Copy only live entries, leaving removed ones behind. */
+ for (i = 0; i < oldCapacity; i++) {
+ oldEntry = (PLDHashEntryHdr *)oldEntryAddr;
+ if (ENTRY_IS_LIVE(oldEntry)) {
+ oldEntry->keyHash &= ~COLLISION_FLAG;
+ newEntry = SearchTable(table, getKey(table, oldEntry),
+ oldEntry->keyHash, PL_DHASH_ADD);
+ PR_ASSERT(PL_DHASH_ENTRY_IS_FREE(newEntry));
+ moveEntry(table, oldEntry, newEntry);
+ newEntry->keyHash = oldEntry->keyHash;
+ }
+ oldEntryAddr += entrySize;
+ }
+
+ table->ops->freeTable(table, oldEntryStore);
+ return PR_TRUE;
+}
+
+PR_IMPLEMENT(PLDHashEntryHdr *) PL_DHASH_FASTCALL
+PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op)
+{
+ PLDHashNumber keyHash;
+ PLDHashEntryHdr *entry;
+ PRUint32 size;
+ int deltaLog2;
+
+ keyHash = table->ops->hashKey(table, key);
+ keyHash *= PL_DHASH_GOLDEN_RATIO;
+
+ /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
+ ENSURE_LIVE_KEYHASH(keyHash);
+ keyHash &= ~COLLISION_FLAG;
+
+ switch (op) {
+ case PL_DHASH_LOOKUP:
+ METER(table->stats.lookups++);
+ entry = SearchTable(table, key, keyHash, op);
+ break;
+
+ case PL_DHASH_ADD:
+ /*
+ * If alpha is >= .75, grow or compress the table. If key is already
+ * in the table, we may grow once more than necessary, but only if we
+ * are on the edge of being overloaded.
+ */
+ size = PL_DHASH_TABLE_SIZE(table);
+ if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) {
+ /* Compress if a quarter or more of all entries are removed. */
+ if (table->removedCount >= size >> 2) {
+ METER(table->stats.compresses++);
+ deltaLog2 = 0;
+ } else {
+ METER(table->stats.grows++);
+ deltaLog2 = 1;
+ }
+
+ /*
+ * Grow or compress table, returning null if ChangeTable fails and
+ * falling through might claim the last free entry.
+ */
+ if (!ChangeTable(table, deltaLog2) &&
+ table->entryCount + table->removedCount == size - 1) {
+ METER(table->stats.addFailures++);
+ return NULL;
+ }
+ }
+
+ /*
+ * Look for entry after possibly growing, so we don't have to add it,
+ * then skip it while growing the table and re-add it after.
+ */
+ entry = SearchTable(table, key, keyHash, op);
+ if (!ENTRY_IS_LIVE(entry)) {
+ /* Initialize the entry, indicating that it's no longer free. */
+ METER(table->stats.addMisses++);
+ if (ENTRY_IS_REMOVED(entry)) {
+ METER(table->stats.addOverRemoved++);
+ table->removedCount--;
+ keyHash |= COLLISION_FLAG;
+ }
+ if (table->ops->initEntry &&
+ !table->ops->initEntry(table, entry, key)) {
+ /* We haven't claimed entry yet; fail with null return. */
+ memset(entry + 1, 0, table->entrySize - sizeof *entry);
+ return NULL;
+ }
+ entry->keyHash = keyHash;
+ table->entryCount++;
+ }
+ METER(else table->stats.addHits++);
+ break;
+
+ case PL_DHASH_REMOVE:
+ entry = SearchTable(table, key, keyHash, op);
+ if (ENTRY_IS_LIVE(entry)) {
+ /* Clear this entry and mark it as "removed". */
+ METER(table->stats.removeHits++);
+ PL_DHashTableRawRemove(table, entry);
+
+ /* Shrink if alpha is <= .25 and table isn't too small already. */
+ size = PL_DHASH_TABLE_SIZE(table);
+ if (size > PL_DHASH_MIN_SIZE &&
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ /** @todo This is where IPC screws up, avoid the assertion in ChangeTable until it's fixed. */
+ table->generation != PR_UINT32_MAX &&
+#endif
+ table->entryCount <= MIN_LOAD(table, size)) {
+ METER(table->stats.shrinks++);
+ (void) ChangeTable(table, -1);
+ }
+ }
+ METER(else table->stats.removeMisses++);
+ entry = NULL;
+ break;
+
+ default:
+ PR_ASSERT(0);
+ entry = NULL;
+ }
+
+ return entry;
+}
+
+PR_IMPLEMENT(void)
+PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ PLDHashNumber keyHash; /* load first in case clearEntry goofs it */
+
+ PR_ASSERT(PL_DHASH_ENTRY_IS_LIVE(entry));
+ keyHash = entry->keyHash;
+ table->ops->clearEntry(table, entry);
+ if (keyHash & COLLISION_FLAG) {
+ MARK_ENTRY_REMOVED(entry);
+ table->removedCount++;
+ } else {
+ METER(table->stats.removeFrees++);
+ MARK_ENTRY_FREE(entry);
+ }
+ table->entryCount--;
+}
+
+PR_IMPLEMENT(PRUint32)
+PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg)
+{
+ char *entryAddr, *entryLimit;
+ PRUint32 i, capacity, entrySize;
+ PRBool didRemove;
+ PLDHashEntryHdr *entry;
+ PLDHashOperator op;
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PRUint32 generation;
+
+ /*
+ * The hack! Set generation to PR_UINT32_MAX during the enumeration so
+ * we can prevent ChangeTable from being called.
+ *
+ * This happens during ipcDConnectService::OnClientStateChange()
+ * / ipcDConnectService::DeleteInstance() now when running
+ * java clienttest list hostinfo and vboxwebsrv crashes. It's quite
+ * likely that the IPC code isn't following the rules here, but it
+ * looks more difficult to fix that just hacking this hash code.
+ */
+ generation = table->generation;
+ table->generation = PR_UINT32_MAX;
+#endif /* VBOX */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ capacity = PL_DHASH_TABLE_SIZE(table);
+ entryLimit = entryAddr + capacity * entrySize;
+ i = 0;
+ didRemove = PR_FALSE;
+ while (entryAddr < entryLimit) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ op = etor(table, entry, i++, arg);
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PR_ASSERT(table->generation == PR_UINT32_MAX);
+#endif
+ if (op & PL_DHASH_REMOVE) {
+ METER(table->stats.removeEnums++);
+ PL_DHashTableRawRemove(table, entry);
+ didRemove = PR_TRUE;
+ }
+ if (op & PL_DHASH_STOP)
+ break;
+ }
+ entryAddr += entrySize;
+ }
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ table->generation = generation;
+#endif
+
+ /*
+ * Shrink or compress if a quarter or more of all entries are removed, or
+ * if the table is underloaded according to the configured minimum alpha,
+ * and is not minimal-size already. Do this only if we removed above, so
+ * non-removing enumerations can count on stable table->entryStore until
+ * the next non-lookup-Operate or removing-Enumerate.
+ */
+ if (didRemove &&
+ (table->removedCount >= capacity >> 2 ||
+ (capacity > PL_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, capacity)))) {
+ METER(table->stats.enumShrinks++);
+ capacity = table->entryCount;
+ capacity += capacity >> 1;
+ if (capacity < PL_DHASH_MIN_SIZE)
+ capacity = PL_DHASH_MIN_SIZE;
+ (void) ChangeTable(table,
+ PR_CeilingLog2(capacity)
+ - (PL_DHASH_BITS - table->hashShift));
+ }
+ return i;
+}
+
+#ifdef PL_DHASHMETER
+#include <math.h>
+
+PR_IMPLEMENT(void)
+PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp)
+{
+ char *entryAddr;
+ PRUint32 entrySize, entryCount;
+ int hashShift, sizeLog2;
+ PRUint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount;
+ PLDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2;
+ double sqsum, mean, variance, sigma;
+ PLDHashEntryHdr *entry, *probe;
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ hashShift = table->hashShift;
+ sizeLog2 = PL_DHASH_BITS - hashShift;
+ tableSize = PL_DHASH_TABLE_SIZE(table);
+ sizeMask = PR_BITMASK(sizeLog2);
+ chainCount = maxChainLen = 0;
+ hash2 = 0;
+ sqsum = 0;
+
+ for (i = 0; i < tableSize; i++) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ entryAddr += entrySize;
+ if (!ENTRY_IS_LIVE(entry))
+ continue;
+ hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift);
+ saveHash1 = hash1;
+ probe = ADDRESS_ENTRY(table, hash1);
+ chainLen = 1;
+ if (probe == entry) {
+ /* Start of a (possibly unit-length) chain. */
+ chainCount++;
+ } else {
+ hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2,
+ hashShift);
+ do {
+ chainLen++;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ probe = ADDRESS_ENTRY(table, hash1);
+ } while (probe != entry);
+ }
+ sqsum += chainLen * chainLen;
+ if (chainLen > maxChainLen) {
+ maxChainLen = chainLen;
+ maxChainHash1 = saveHash1;
+ maxChainHash2 = hash2;
+ }
+ }
+
+ entryCount = table->entryCount;
+ if (entryCount && chainCount) {
+ mean = (double)entryCount / chainCount;
+ variance = chainCount * sqsum - entryCount * entryCount;
+ if (variance < 0 || chainCount == 1)
+ variance = 0;
+ else
+ variance /= chainCount * (chainCount - 1);
+ sigma = sqrt(variance);
+ } else {
+ mean = sigma = 0;
+ }
+
+ fprintf(fp, "Double hashing statistics:\n");
+ fprintf(fp, " table size (in entries): %u\n", tableSize);
+ fprintf(fp, " number of entries: %u\n", table->entryCount);
+ fprintf(fp, " number of removed entries: %u\n", table->removedCount);
+ fprintf(fp, " number of searches: %u\n", table->stats.searches);
+ fprintf(fp, " number of hits: %u\n", table->stats.hits);
+ fprintf(fp, " number of misses: %u\n", table->stats.misses);
+ fprintf(fp, " mean steps per search: %g\n", table->stats.searches ?
+ (double)table->stats.steps
+ / table->stats.searches :
+ 0.);
+ fprintf(fp, " mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " number of lookups: %u\n", table->stats.lookups);
+ fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses);
+ fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved);
+ fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits);
+ fprintf(fp, " add failures: %u\n", table->stats.addFailures);
+ fprintf(fp, " useful removes: %u\n", table->stats.removeHits);
+ fprintf(fp, " useless removes: %u\n", table->stats.removeMisses);
+ fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees);
+ fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums);
+ fprintf(fp, " number of grows: %u\n", table->stats.grows);
+ fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks);
+ fprintf(fp, " number of compresses: %u\n", table->stats.compresses);
+ fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks);
+
+ if (dump && maxChainLen && hash2) {
+ fputs("Maximum hash chain:\n", fp);
+ hash1 = maxChainHash1;
+ hash2 = maxChainHash2;
+ entry = ADDRESS_ENTRY(table, hash1);
+ i = 0;
+ do {
+ if (dump(table, entry, i++, fp) != PL_DHASH_NEXT)
+ break;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ entry = ADDRESS_ENTRY(table, hash1);
+ } while (PL_DHASH_ENTRY_IS_BUSY(entry));
+ }
+}
+#endif /* PL_DHASHMETER */
diff --git a/src/libs/xpcom18a4/xpcom/ds/pldhash.h b/src/libs/xpcom18a4/xpcom/ds/pldhash.h
new file mode 100644
index 00000000..8c4347c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/pldhash.h
@@ -0,0 +1,603 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef pldhash_h___
+#define pldhash_h___
+/*
+ * Double hashing, a la Knuth 6.
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+ */
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_DHashTableInit VBoxNsplPL_DHashTableInit
+#define PL_DHashTableFinish VBoxNsplPL_DHashTableFinish
+#define PL_DHashTableOperate VBoxNsplPL_DHashTableOperate
+#define PL_DHashTableEnumerate VBoxNsplPL_DHashTableEnumerate
+#define PL_DHashAllocTable VBoxNsplPL_DHashAllocTable
+#define PL_DHashFreeTable VBoxNsplPL_DHashFreeTable
+#define PL_DHashMoveEntryStub VBoxNsplPL_DHashMoveEntryStub
+#define PL_DHashFinalizeStub VBoxNsplPL_DHashFinalizeStub
+#define PL_DHashClearEntryStub VBoxNsplPL_DHashClearEntryStub
+#define PL_DHashFreeStringKey VBoxNsplPL_DHashFreeStringKey
+#define PL_DHashGetKeyStub VBoxNsplPL_DHashGetKeyStub
+#define PL_DHashGetStubOps VBoxNsplPL_DHashGetStubOps
+#define PL_DHashMatchEntryStub VBoxNsplPL_DHashMatchEntryStub
+#define PL_DHashMatchStringKey VBoxNsplPL_DHashMatchStringKey
+#define PL_DHashStringKey VBoxNsplPL_DHashStringKey
+#define PL_DHashTableDestroy VBoxNsplPL_DHashTableDestroy
+#define PL_DHashTableRawRemove VBoxNsplPL_DHashTableRawRemove
+#define PL_DHashTableSetAlphaBounds VBoxNsplPL_DHashTableSetAlphaBounds
+#define PL_DHashVoidPtrKeyStub VBoxNsplPL_DHashVoidPtrKeyStub
+#define PL_NewDHashTable VBoxNsplPL_NewDHashTable
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+#ifdef DEBUG_XXXbrendan
+#define PL_DHASHMETER 1
+#endif
+
+#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define PL_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
+#else
+#define PL_DHASH_FASTCALL
+#endif
+
+/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
+#undef PL_DHASH_SIZE_LIMIT
+#define PL_DHASH_SIZE_LIMIT PR_BIT(24)
+
+/* Minimum table size, or gross entry count (net is at most .75 loaded). */
+#ifndef PL_DHASH_MIN_SIZE
+#define PL_DHASH_MIN_SIZE 16
+#elif (PL_DHASH_MIN_SIZE & (PL_DHASH_MIN_SIZE - 1)) != 0
+#error "PL_DHASH_MIN_SIZE must be a power of two!"
+#endif
+
+/*
+ * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
+ * expressed as a fixed-point 32-bit fraction.
+ */
+#define PL_DHASH_BITS 32
+#define PL_DHASH_GOLDEN_RATIO 0x9E3779B9U
+
+/* Primitive and forward-struct typedefs. */
+typedef PRUint32 PLDHashNumber;
+typedef struct PLDHashEntryHdr PLDHashEntryHdr;
+typedef struct PLDHashEntryStub PLDHashEntryStub;
+typedef struct PLDHashTable PLDHashTable;
+typedef struct PLDHashTableOps PLDHashTableOps;
+
+/*
+ * Table entry header structure.
+ *
+ * In order to allow in-line allocation of key and value, we do not declare
+ * either here. Instead, the API uses const void *key as a formal parameter,
+ * and asks each entry for its key when necessary via a getKey callback, used
+ * when growing or shrinking the table. Other callback types are defined
+ * below and grouped into the PLDHashTableOps structure, for single static
+ * initialization per hash table sub-type.
+ *
+ * Each hash table sub-type should nest the PLDHashEntryHdr structure at the
+ * front of its particular entry type. The keyHash member contains the result
+ * of multiplying the hash code returned from the hashKey callback (see below)
+ * by PL_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
+ * and 1 values. The stored keyHash value is table size invariant, and it is
+ * maintained automatically by PL_DHashTableOperate -- users should never set
+ * it, and its only uses should be via the entry macros below.
+ *
+ * The PL_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
+ * removed. An entry may be either busy or free; if busy, it may be live or
+ * removed. Consumers of this API should not access members of entries that
+ * are not live.
+ *
+ * However, use PL_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
+ * returned by PL_DHashTableOperate, as PL_DHashTableOperate never returns a
+ * non-live, busy (i.e., removed) entry pointer to its caller. See below for
+ * more details on PL_DHashTableOperate's calling rules.
+ */
+struct PLDHashEntryHdr {
+ PLDHashNumber keyHash; /* every entry must begin like this */
+};
+
+#define PL_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0)
+#define PL_DHASH_ENTRY_IS_BUSY(entry) (!PL_DHASH_ENTRY_IS_FREE(entry))
+#define PL_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
+
+/*
+ * A PLDHashTable is currently 8 words (without the PL_DHASHMETER overhead)
+ * on most architectures, and may be allocated on the stack or within another
+ * structure or class (see below for the Init and Finish functions to use).
+ *
+ * To decide whether to use double hashing vs. chaining, we need to develop a
+ * trade-off relation, as follows:
+ *
+ * Let alpha be the load factor, esize the entry size in words, count the
+ * entry count, and pow2 the power-of-two table size in entries.
+ *
+ * (PLDHashTable overhead) > (PLHashTable overhead)
+ * (unused table entry space) > (malloc and .next overhead per entry) +
+ * (buckets overhead)
+ * (1 - alpha) * esize * pow2 > 2 * count + pow2
+ *
+ * Notice that alpha is by definition (count / pow2):
+ *
+ * (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
+ * (1 - alpha) * esize > 2 * alpha + 1
+ *
+ * esize > (1 + 2 * alpha) / (1 - alpha)
+ *
+ * This assumes both tables must keep keyHash, key, and value for each entry,
+ * where key and value point to separately allocated strings or structures.
+ * If key and value can be combined into one pointer, then the trade-off is:
+ *
+ * esize > (1 + 3 * alpha) / (1 - alpha)
+ *
+ * If the entry value can be a subtype of PLDHashEntryHdr, rather than a type
+ * that must be allocated separately and referenced by an entry.value pointer
+ * member, and provided key's allocation can be fused with its entry's, then
+ * k (the words wasted per entry with chaining) is 4.
+ *
+ * To see these curves, feed gnuplot input like so:
+ *
+ * gnuplot> f(x,k) = (1 + k * x) / (1 - x)
+ * gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
+ *
+ * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
+ * words for chaining to be more space-efficient than double hashing.
+ *
+ * Solving for alpha helps us decide when to shrink an underloaded table:
+ *
+ * esize > (1 + k * alpha) / (1 - alpha)
+ * esize - alpha * esize > 1 + k * alpha
+ * esize - 1 > (k + esize) * alpha
+ * (esize - 1) / (k + esize) > alpha
+ *
+ * alpha < (esize - 1) / (esize + k)
+ *
+ * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
+ * assuming esize is not too large (in which case, chaining should probably be
+ * used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3
+ * and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5
+ * would still obtain. See the PL_DHASH_MIN_ALPHA macro further below.
+ *
+ * The current implementation uses a configurable lower bound on alpha, which
+ * defaults to .25, when deciding to shrink the table (while still respecting
+ * PL_DHASH_MIN_SIZE).
+ *
+ * Note a qualitative difference between chaining and double hashing: under
+ * chaining, entry addresses are stable across table shrinks and grows. With
+ * double hashing, you can't safely hold an entry pointer and use it after an
+ * ADD or REMOVE operation, unless you sample table->generation before adding
+ * or removing, and compare the sample after, dereferencing the entry pointer
+ * only if table->generation has not changed.
+ *
+ * The moral of this story: there is no one-size-fits-all hash table scheme,
+ * but for small table entry size, and assuming entry address stability is not
+ * required, double hashing wins.
+ */
+struct PLDHashTable {
+ const PLDHashTableOps *ops; /* virtual operations, see below */
+ void *data; /* ops- and instance-specific data */
+ PRInt16 hashShift; /* multiplicative hash shift */
+ uint8 maxAlphaFrac; /* 8-bit fixed point max alpha */
+ uint8 minAlphaFrac; /* 8-bit fixed point min alpha */
+ PRUint32 entrySize; /* number of bytes in an entry */
+ PRUint32 entryCount; /* number of entries in table */
+ PRUint32 removedCount; /* removed entry sentinels in table */
+ PRUint32 generation; /* entry storage generation number */
+ char *entryStore; /* entry storage */
+#ifdef PL_DHASHMETER
+ struct PLDHashStats {
+ PRUint32 searches; /* total number of table searches */
+ PRUint32 steps; /* hash chain links traversed */
+ PRUint32 hits; /* searches that found key */
+ PRUint32 misses; /* searches that didn't find key */
+ PRUint32 lookups; /* number of PL_DHASH_LOOKUPs */
+ PRUint32 addMisses; /* adds that miss, and do work */
+ PRUint32 addOverRemoved; /* adds that recycled a removed entry */
+ PRUint32 addHits; /* adds that hit an existing entry */
+ PRUint32 addFailures; /* out-of-memory during add growth */
+ PRUint32 removeHits; /* removes that hit, and do work */
+ PRUint32 removeMisses; /* useless removes that miss */
+ PRUint32 removeFrees; /* removes that freed entry directly */
+ PRUint32 removeEnums; /* removes done by Enumerate */
+ PRUint32 grows; /* table expansions */
+ PRUint32 shrinks; /* table contractions */
+ PRUint32 compresses; /* table compressions */
+ PRUint32 enumShrinks; /* contractions after Enumerate */
+ } stats;
+#endif
+};
+
+/*
+ * Size in entries (gross, not net of free and removed sentinels) for table.
+ * We store hashShift rather than sizeLog2 to optimize the collision-free case
+ * in SearchTable.
+ */
+#define PL_DHASH_TABLE_SIZE(table) PR_BIT(PL_DHASH_BITS - (table)->hashShift)
+
+/*
+ * Table space at entryStore is allocated and freed using these callbacks.
+ * The allocator should return null on error only (not if called with nbytes
+ * equal to 0; but note that pldhash.c code will never call with 0 nbytes).
+ */
+typedef void *
+(* PR_CALLBACK PLDHashAllocTable)(PLDHashTable *table, PRUint32 nbytes);
+
+typedef void
+(* PR_CALLBACK PLDHashFreeTable) (PLDHashTable *table, void *ptr);
+
+/*
+ * When a table grows or shrinks, each entry is queried for its key using this
+ * callback. NB: in that event, entry is not in table any longer; it's in the
+ * old entryStore vector, which is due to be freed once all entries have been
+ * moved via moveEntry callbacks.
+ */
+typedef const void *
+(* PR_CALLBACK PLDHashGetKey) (PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+/*
+ * Compute the hash code for a given key to be looked up, added, or removed
+ * from table. A hash code may have any PLDHashNumber value.
+ */
+typedef PLDHashNumber
+(* PR_CALLBACK PLDHashHashKey) (PLDHashTable *table, const void *key);
+
+/*
+ * Compare the key identifying entry in table with the provided key parameter.
+ * Return PR_TRUE if keys match, PR_FALSE otherwise.
+ */
+typedef PRBool
+(* PR_CALLBACK PLDHashMatchEntry)(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Copy the data starting at from to the new entry storage at to. Do not add
+ * reference counts for any strong references in the entry, however, as this
+ * is a "move" operation: the old entry storage at from will be freed without
+ * any reference-decrementing callback shortly.
+ */
+typedef void
+(* PR_CALLBACK PLDHashMoveEntry)(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+/*
+ * Clear the entry and drop any strong references it holds. This callback is
+ * invoked during a PL_DHASH_REMOVE operation (see below for operation codes),
+ * but only if the given key is found in the table.
+ */
+typedef void
+(* PR_CALLBACK PLDHashClearEntry)(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+/*
+ * Called when a table (whether allocated dynamically by itself, or nested in
+ * a larger structure, or allocated on the stack) is finished. This callback
+ * allows table->ops-specific code to finalize table->data.
+ */
+typedef void
+(* PR_CALLBACK PLDHashFinalize) (PLDHashTable *table);
+
+/*
+ * Initialize a new entry, apart from keyHash. This function is called when
+ * PL_DHashTableOperate's PL_DHASH_ADD case finds no existing entry for the
+ * given key, and must add a new one. At that point, entry->keyHash is not
+ * set yet, to avoid claiming the last free entry in a severely overloaded
+ * table.
+ */
+typedef PRBool
+(* PR_CALLBACK PLDHashInitEntry)(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Finally, the "vtable" structure for PLDHashTable. The first eight hooks
+ * must be provided by implementations; they're called unconditionally by the
+ * generic pldhash.c code. Hooks after these may be null.
+ *
+ * Summary of allocation-related hook usage with C++ placement new emphasis:
+ * allocTable Allocate raw bytes with malloc, no ctors run.
+ * freeTable Free raw bytes with free, no dtors run.
+ * initEntry Call placement new using default key-based ctor.
+ * Return PR_TRUE on success, PR_FALSE on error.
+ * moveEntry Call placement new using copy ctor, run dtor on old
+ * entry storage.
+ * clearEntry Run dtor on entry.
+ * finalize Stub unless table->data was initialized and needs to
+ * be finalized.
+ *
+ * Note the reason why initEntry is optional: the default hooks (stubs) clear
+ * entry storage: On successful PL_DHashTableOperate(tbl, key, PL_DHASH_ADD),
+ * the returned entry pointer addresses an entry struct whose keyHash member
+ * has been set non-zero, but all other entry members are still clear (null).
+ * PL_DHASH_ADD callers can test such members to see whether the entry was
+ * newly created by the PL_DHASH_ADD call that just succeeded. If placement
+ * new or similar initialization is required, define an initEntry hook. Of
+ * course, the clearEntry hook must zero or null appropriately.
+ *
+ * XXX assumes 0 is null for pointer types.
+ */
+struct PLDHashTableOps {
+ /* Mandatory hooks. All implementations must provide these. */
+ PLDHashAllocTable allocTable;
+ PLDHashFreeTable freeTable;
+ PLDHashGetKey getKey;
+ PLDHashHashKey hashKey;
+ PLDHashMatchEntry matchEntry;
+ PLDHashMoveEntry moveEntry;
+ PLDHashClearEntry clearEntry;
+ PLDHashFinalize finalize;
+
+ /* Optional hooks start here. If null, these are not called. */
+ PLDHashInitEntry initEntry;
+};
+
+/*
+ * Default implementations for the above ops.
+ */
+PR_EXTERN(void *)
+PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes);
+
+PR_EXTERN(void)
+PL_DHashFreeTable(PLDHashTable *table, void *ptr);
+
+PR_EXTERN(PLDHashNumber)
+PL_DHashStringKey(PLDHashTable *table, const void *key);
+
+/* A minimal entry contains a keyHash header and a void key pointer. */
+struct PLDHashEntryStub {
+ PLDHashEntryHdr hdr;
+ const void *key;
+};
+
+PR_EXTERN(const void *)
+PL_DHashGetKeyStub(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(PLDHashNumber)
+PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key);
+
+PR_EXTERN(PRBool)
+PL_DHashMatchEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+PR_EXTERN(PRBool)
+PL_DHashMatchStringKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+PR_EXTERN(void)
+PL_DHashMoveEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+PR_EXTERN(void)
+PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(void)
+PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(void)
+PL_DHashFinalizeStub(PLDHashTable *table);
+
+/*
+ * If you use PLDHashEntryStub or a subclass of it as your entry struct, and
+ * if your entries move via memcpy and clear via memset(0), you can use these
+ * stub operations.
+ */
+PR_EXTERN(const PLDHashTableOps *)
+PL_DHashGetStubOps(void);
+
+/*
+ * Dynamically allocate a new PLDHashTable using malloc, initialize it using
+ * PL_DHashTableInit, and return its address. Return null on malloc failure.
+ * Note that the entry storage at table->entryStore will be allocated using
+ * the ops->allocTable callback.
+ */
+PR_EXTERN(PLDHashTable *)
+PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize,
+ PRUint32 capacity);
+
+/*
+ * Finalize table's data, free its entry storage (via table->ops->freeTable),
+ * and return the memory starting at table to the malloc heap.
+ */
+PR_EXTERN(void)
+PL_DHashTableDestroy(PLDHashTable *table);
+
+/*
+ * Initialize table with ops, data, entrySize, and capacity. Capacity is a
+ * guess for the smallest table size at which the table will usually be less
+ * than 75% loaded (the table will grow or shrink as needed; capacity serves
+ * only to avoid inevitable early growth from PL_DHASH_MIN_SIZE).
+ */
+PR_EXTERN(PRBool)
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+ PRUint32 entrySize, PRUint32 capacity);
+
+/*
+ * Set maximum and minimum alpha for table. The defaults are 0.75 and .25.
+ * maxAlpha must be in [0.5, 0.9375] for the default PL_DHASH_MIN_SIZE; or if
+ * MinSize=PL_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
+ * else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that
+ * we don't shrink on the very next remove after growing a table upon adding
+ * an entry that brings entryCount past maxAlpha * tableSize.
+ */
+PR_IMPLEMENT(void)
+PL_DHashTableSetAlphaBounds(PLDHashTable *table,
+ float maxAlpha,
+ float minAlpha);
+
+/*
+ * Call this macro with k, the number of pointer-sized words wasted per entry
+ * under chaining, to compute the minimum alpha at which double hashing still
+ * beats chaining.
+ */
+#define PL_DHASH_MIN_ALPHA(table, k) \
+ ((float)((table)->entrySize / sizeof(void *) - 1) \
+ / ((table)->entrySize / sizeof(void *) + (k)))
+
+/*
+ * Finalize table's data, free its entry storage using table->ops->freeTable,
+ * and leave its members unchanged from their last live values (which leaves
+ * pointers dangling). If you want to burn cycles clearing table, it's up to
+ * your code to call memset.
+ */
+PR_EXTERN(void)
+PL_DHashTableFinish(PLDHashTable *table);
+
+/*
+ * To consolidate keyHash computation and table grow/shrink code, we use a
+ * single entry point for lookup, add, and remove operations. The operation
+ * codes are declared here, along with codes returned by PLDHashEnumerator
+ * functions, which control PL_DHashTableEnumerate's behavior.
+ */
+typedef enum PLDHashOperator {
+ PL_DHASH_LOOKUP = 0, /* lookup entry */
+ PL_DHASH_ADD = 1, /* add entry */
+ PL_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
+ PL_DHASH_NEXT = 0, /* enumerator says continue */
+ PL_DHASH_STOP = 1 /* enumerator says stop */
+} PLDHashOperator;
+
+/*
+ * To lookup a key in table, call:
+ *
+ * entry = PL_DHashTableOperate(table, key, PL_DHASH_LOOKUP);
+ *
+ * If PL_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
+ * entry. If PL_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
+ *
+ * To add an entry identified by key to table, call:
+ *
+ * entry = PL_DHashTableOperate(table, key, PL_DHASH_ADD);
+ *
+ * If entry is null upon return, then either the table is severely overloaded,
+ * and memory can't be allocated for entry storage via table->ops->allocTable;
+ * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
+ * have returned false.
+ *
+ * Otherwise, entry->keyHash has been set so that PL_DHASH_ENTRY_IS_BUSY(entry)
+ * is true, and it is up to the caller to initialize the key and value parts
+ * of the entry sub-type, if they have not been set already (i.e. if entry was
+ * not already in the table, and if the optional initEntry hook was not used).
+ *
+ * To remove an entry identified by key from table, call:
+ *
+ * (void) PL_DHashTableOperate(table, key, PL_DHASH_REMOVE);
+ *
+ * If key's entry is found, it is cleared (via table->ops->clearEntry) and
+ * the entry is marked so that PL_DHASH_ENTRY_IS_FREE(entry). This operation
+ * returns null unconditionally; you should ignore its return value.
+ */
+PR_EXTERN(PLDHashEntryHdr *) PL_DHASH_FASTCALL
+PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op);
+
+/*
+ * Remove an entry already accessed via LOOKUP or ADD.
+ *
+ * NB: this is a "raw" or low-level routine, intended to be used only where
+ * the inefficiency of a full PL_DHashTableOperate (which rehashes in order
+ * to find the entry given its key) is not tolerable. This function does not
+ * shrink the table if it is underloaded. It does not update stats #ifdef
+ * PL_DHASHMETER, either.
+ */
+PR_EXTERN(void)
+PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+/*
+ * Enumerate entries in table using etor:
+ *
+ * count = PL_DHashTableEnumerate(table, etor, arg);
+ *
+ * PL_DHashTableEnumerate calls etor like so:
+ *
+ * op = etor(table, entry, number, arg);
+ *
+ * where number is a zero-based ordinal assigned to live entries according to
+ * their order in table->entryStore.
+ *
+ * The return value, op, is treated as a set of flags. If op is PL_DHASH_NEXT,
+ * then continue enumerating. If op contains PL_DHASH_REMOVE, then clear (via
+ * table->ops->clearEntry) and free entry. Then we check whether op contains
+ * PL_DHASH_STOP; if so, stop enumerating and return the number of live entries
+ * that were enumerated so far. Return the total number of live entries when
+ * enumeration completes normally.
+ *
+ * If etor calls PL_DHashTableOperate on table with op != PL_DHASH_LOOKUP, it
+ * must return PL_DHASH_STOP; otherwise undefined behavior results.
+ *
+ * If any enumerator returns PL_DHASH_REMOVE, table->entryStore may be shrunk
+ * or compressed after enumeration, but before PL_DHashTableEnumerate returns.
+ * Such an enumerator therefore can't safely set aside entry pointers, but an
+ * enumerator that never returns PL_DHASH_REMOVE can set pointers to entries
+ * aside, e.g., to avoid copying live entries into an array of the entry type.
+ * Copying entry pointers is cheaper, and safe so long as the caller of such a
+ * "stable" Enumerate doesn't use the set-aside pointers after any call either
+ * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
+ * grow or shrink entryStore.
+ *
+ * If your enumerator wants to remove certain entries, but set aside pointers
+ * to other entries that it retains, it can use PL_DHashTableRawRemove on the
+ * entries to be removed, returning PL_DHASH_NEXT to skip them. Likewise, if
+ * you want to remove entries, but for some reason you do not want entryStore
+ * to be shrunk or compressed, you can call PL_DHashTableRawRemove safely on
+ * the entry being enumerated, rather than returning PL_DHASH_REMOVE.
+ */
+typedef PLDHashOperator
+(* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg);
+
+PR_EXTERN(PRUint32)
+PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg);
+
+#ifdef PL_DHASHMETER
+#include <stdio.h>
+
+PR_EXTERN(void)
+PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp);
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* pldhash_h___ */